Flutter Impeller
path_tessellator_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 "flutter/testing/testing.h"
6 #include "gmock/gmock.h"
7 #include "gtest/gtest.h"
8 
10 
11 #include "flutter/display_list/geometry/dl_path.h"
12 #include "flutter/display_list/geometry/dl_path_builder.h"
13 
14 namespace impeller {
15 namespace testing {
16 
18  public:
19  MOCK_METHOD(void, Write, (Point point), (override));
20  MOCK_METHOD(void, EndContour, (), (override));
21 };
22 
24  public:
27  (Point origin, bool will_be_closed),
28  (override));
29  MOCK_METHOD(void, RecordLine, (Point p1, Point p2), (override));
30  MOCK_METHOD(void, RecordQuad, (Point p1, Point cp, Point p2), (override));
33  (Point p1, Point cp, Point p2, Scalar weight),
34  (override));
37  (Point p1, Point cp1, Point cp2, Point p2),
38  (override));
39  MOCK_METHOD(void, EndContour, (Point origin, bool with_close), (override));
40 };
41 
42 TEST(PathTessellatorTest, EmptyPath) {
43  flutter::DlPathBuilder builder;
44  builder.MoveTo({0, 0});
45  flutter::DlPath path = builder.TakePath();
46 
47  ::testing::StrictMock<MockSegmentReceiver> mock_receiver;
48  PathTessellator::PathToFilledSegments(path, mock_receiver);
49 
51  EXPECT_EQ(points, 0u);
52  EXPECT_EQ(contours, 0u);
53 
54  ::testing::StrictMock<MockPathVertexWriter> mock_writer;
55  PathTessellator::PathToFilledVertices(path, mock_writer, 1.0f);
56 }
57 
58 TEST(PathTessellatorTest, EmptyPathMultipleMoveTo) {
59  flutter::DlPathBuilder builder;
60  builder.MoveTo({0, 0});
61  builder.MoveTo({10, 10});
62  builder.MoveTo({20, 20});
63  flutter::DlPath path = builder.TakePath();
64 
65  ::testing::StrictMock<MockSegmentReceiver> mock_receiver;
66  PathTessellator::PathToFilledSegments(path, mock_receiver);
67 
69  EXPECT_EQ(points, 0u);
70  EXPECT_EQ(contours, 0u);
71 
72  ::testing::StrictMock<MockPathVertexWriter> mock_writer;
73  PathTessellator::PathToFilledVertices(path, mock_writer, 1.0f);
74 }
75 
76 TEST(PathTessellatorTest, SimpleClosedPath) {
77  flutter::DlPathBuilder builder;
78  builder.MoveTo({0, 0});
79  builder.LineTo({10, 10});
80  builder.LineTo({0, 20});
81  builder.Close();
82  flutter::DlPath path = builder.TakePath();
83 
84  ::testing::StrictMock<MockSegmentReceiver> mock_receiver;
85  {
86  ::testing::InSequence sequence;
87 
88  EXPECT_CALL(mock_receiver,
89  BeginContour(Point(0, 0), /*will_be_closed=*/true));
90  EXPECT_CALL(mock_receiver, RecordLine(Point(0, 0), Point(10, 10)));
91  EXPECT_CALL(mock_receiver, RecordLine(Point(10, 10), Point(0, 20)));
92  EXPECT_CALL(mock_receiver, RecordLine(Point(0, 20), Point(0, 0)));
93  EXPECT_CALL(mock_receiver, EndContour(Point(0, 0), /*with_close=*/true));
94  }
95  PathTessellator::PathToFilledSegments(path, mock_receiver);
96 
98  EXPECT_EQ(points, 4u);
99  EXPECT_EQ(contours, 1u);
100 
101  ::testing::StrictMock<MockPathVertexWriter> mock_writer;
102  {
103  ::testing::InSequence sequence;
104 
105  EXPECT_CALL(mock_writer, Write(Point(0, 0)));
106  EXPECT_CALL(mock_writer, Write(Point(10, 10)));
107  EXPECT_CALL(mock_writer, Write(Point(0, 20)));
108  EXPECT_CALL(mock_writer, Write(Point(0, 0)));
109  EXPECT_CALL(mock_writer, EndContour());
110  }
111  PathTessellator::PathToFilledVertices(path, mock_writer, 1.0f);
112 }
113 
114 TEST(PathTessellatorTest, SimpleUnclosedPath) {
115  flutter::DlPathBuilder builder;
116  builder.MoveTo({0, 0});
117  builder.LineTo({10, 10});
118  builder.LineTo({0, 20});
119  // Close not really needed for filled paths
120  flutter::DlPath path = builder.TakePath();
121 
122  ::testing::StrictMock<MockSegmentReceiver> mock_receiver;
123  {
124  ::testing::InSequence sequence;
125 
126  EXPECT_CALL(mock_receiver,
127  BeginContour(Point(0, 0), /*will_be_closed=*/false));
128  EXPECT_CALL(mock_receiver, RecordLine(Point(0, 0), Point(10, 10)));
129  EXPECT_CALL(mock_receiver, RecordLine(Point(10, 10), Point(0, 20)));
130  EXPECT_CALL(mock_receiver, RecordLine(Point(0, 20), Point(0, 0)));
131  EXPECT_CALL(mock_receiver, EndContour(Point(0, 0), /*with_close=*/false));
132  }
133  PathTessellator::PathToFilledSegments(path, mock_receiver);
134 
135  auto [points, contours] = PathTessellator::CountFillStorage(path, 1.0f);
136  EXPECT_EQ(points, 4u);
137  EXPECT_EQ(contours, 1u);
138 
139  ::testing::StrictMock<MockPathVertexWriter> mock_writer;
140  {
141  ::testing::InSequence sequence;
142 
143  EXPECT_CALL(mock_writer, Write(Point(0, 0)));
144  EXPECT_CALL(mock_writer, Write(Point(10, 10)));
145  EXPECT_CALL(mock_writer, Write(Point(0, 20)));
146  EXPECT_CALL(mock_writer, Write(Point(0, 0)));
147  EXPECT_CALL(mock_writer, EndContour());
148  }
149  PathTessellator::PathToFilledVertices(path, mock_writer, 1.0f);
150 }
151 
152 TEST(PathTessellatorTest, SimplePathTrailingMoveTo) {
153  flutter::DlPathBuilder builder;
154  builder.MoveTo({0, 0});
155  builder.LineTo({10, 10});
156  builder.LineTo({0, 20});
157  builder.Close();
158  builder.MoveTo({500, 100});
159  flutter::DlPath path = builder.TakePath();
160 
161  ::testing::StrictMock<MockSegmentReceiver> mock_receiver;
162  {
163  ::testing::InSequence sequence;
164 
165  EXPECT_CALL(mock_receiver,
166  BeginContour(Point(0, 0), /*will_be_closed=*/true));
167  EXPECT_CALL(mock_receiver, RecordLine(Point(0, 0), Point(10, 10)));
168  EXPECT_CALL(mock_receiver, RecordLine(Point(10, 10), Point(0, 20)));
169  EXPECT_CALL(mock_receiver, RecordLine(Point(0, 20), Point(0, 0)));
170  EXPECT_CALL(mock_receiver, EndContour(Point(0, 0), /*with_close=*/true));
171  }
172  PathTessellator::PathToFilledSegments(path, mock_receiver);
173 
174  auto [points, contours] = PathTessellator::CountFillStorage(path, 1.0f);
175  EXPECT_EQ(points, 4u);
176  EXPECT_EQ(contours, 1u);
177 
178  ::testing::StrictMock<MockPathVertexWriter> mock_writer;
179  {
180  ::testing::InSequence sequence;
181 
182  EXPECT_CALL(mock_writer, Write(Point(0, 0)));
183  EXPECT_CALL(mock_writer, Write(Point(10, 10)));
184  EXPECT_CALL(mock_writer, Write(Point(0, 20)));
185  EXPECT_CALL(mock_writer, Write(Point(0, 0)));
186  EXPECT_CALL(mock_writer, EndContour());
187  }
188  PathTessellator::PathToFilledVertices(path, mock_writer, 1.0f);
189 }
190 
191 TEST(PathTessellatorTest, DegenerateSegmentsPath) {
192  flutter::DlPathBuilder builder;
193  builder.MoveTo({0, 0});
194  builder.LineTo({0, 0});
195  builder.LineTo({0, 0});
196  builder.QuadraticCurveTo({0, 0}, {0, 0});
197  builder.QuadraticCurveTo({0, 0}, {0, 0});
198  builder.ConicCurveTo({0, 0}, {0, 0}, 12.0f);
199  builder.ConicCurveTo({0, 0}, {0, 0}, 12.0f);
200  builder.CubicCurveTo({0, 0}, {0, 0}, {0, 0});
201  builder.CubicCurveTo({0, 0}, {0, 0}, {0, 0});
202  builder.Close();
203  flutter::DlPath path = builder.TakePath();
204 
205  ::testing::StrictMock<MockSegmentReceiver> mock_receiver;
206  {
207  ::testing::InSequence sequence;
208 
209  EXPECT_CALL(mock_receiver,
210  BeginContour(Point(0, 0), /*will_be_closed=*/true));
211  EXPECT_CALL(mock_receiver, EndContour(Point(0, 0), /*with_close=*/true));
212  }
213  PathTessellator::PathToFilledSegments(path, mock_receiver);
214 
215  auto [points, contours] = PathTessellator::CountFillStorage(path, 1.0f);
216  EXPECT_EQ(points, 1u);
217  EXPECT_EQ(contours, 1u);
218 
219  ::testing::StrictMock<MockPathVertexWriter> mock_writer;
220  {
221  ::testing::InSequence sequence;
222 
223  EXPECT_CALL(mock_writer, Write(Point(0, 0)));
224  EXPECT_CALL(mock_writer, EndContour());
225  }
226  PathTessellator::PathToFilledVertices(path, mock_writer, 1.0f);
227 }
228 
229 TEST(PathTessellatorTest, QuadToLineToOptimization) {
230  flutter::DlPathBuilder builder;
231  builder.MoveTo({0, 0});
232  // CP == P1
233  builder.QuadraticCurveTo({0, 0}, {10, 10});
234  // CP == P2
235  builder.QuadraticCurveTo({20, 10}, {20, 10});
236  builder.Close();
237  flutter::DlPath path = builder.TakePath();
238 
239  ::testing::StrictMock<MockSegmentReceiver> mock_receiver;
240  {
241  ::testing::InSequence sequence;
242 
243  EXPECT_CALL(mock_receiver,
244  BeginContour(Point(0, 0), /*will_be_closed=*/true));
245  EXPECT_CALL(mock_receiver, RecordLine(Point(0, 0), Point(10, 10)));
246  EXPECT_CALL(mock_receiver, RecordLine(Point(10, 10), Point(20, 10)));
247  EXPECT_CALL(mock_receiver, RecordLine(Point(20, 10), Point(0, 0)));
248  EXPECT_CALL(mock_receiver, EndContour(Point(0, 0), /*with_close=*/true));
249  }
250  PathTessellator::PathToFilledSegments(path, mock_receiver);
251 
252  auto [points, contours] = PathTessellator::CountFillStorage(path, 1.0f);
253  EXPECT_EQ(points, 4u);
254  EXPECT_EQ(contours, 1u);
255 
256  ::testing::StrictMock<MockPathVertexWriter> mock_writer;
257  {
258  ::testing::InSequence sequence;
259 
260  EXPECT_CALL(mock_writer, Write(Point(0, 0)));
261  EXPECT_CALL(mock_writer, Write(Point(10, 10)));
262  EXPECT_CALL(mock_writer, Write(Point(20, 10)));
263  EXPECT_CALL(mock_writer, Write(Point(0, 0)));
264  EXPECT_CALL(mock_writer, EndContour());
265  }
266  PathTessellator::PathToFilledVertices(path, mock_writer, 1.0f);
267 }
268 
269 TEST(PathTessellatorTest, ConicToLineToOptimization) {
270  flutter::DlPathBuilder builder;
271  builder.MoveTo({0, 0});
272  // CP == P1
273  builder.ConicCurveTo({0, 0}, {10, 10}, 2.0f);
274  // CP == P2
275  builder.ConicCurveTo({20, 10}, {20, 10}, 2.0f);
276  // weight == 0
277  builder.ConicCurveTo({20, 0}, {10, 0}, 0.0f);
278  builder.Close();
279  flutter::DlPath path = builder.TakePath();
280 
281  ::testing::StrictMock<MockSegmentReceiver> mock_receiver;
282  {
283  ::testing::InSequence sequence;
284 
285  EXPECT_CALL(mock_receiver,
286  BeginContour(Point(0, 0), /*will_be_closed=*/true));
287  EXPECT_CALL(mock_receiver, RecordLine(Point(0, 0), Point(10, 10)));
288  EXPECT_CALL(mock_receiver, RecordLine(Point(10, 10), Point(20, 10)));
289  EXPECT_CALL(mock_receiver, RecordLine(Point(20, 10), Point(10, 0)));
290  EXPECT_CALL(mock_receiver, RecordLine(Point(10, 0), Point(0, 0)));
291  EXPECT_CALL(mock_receiver, EndContour(Point(0, 0), /*with_close=*/true));
292  }
293  PathTessellator::PathToFilledSegments(path, mock_receiver);
294 
295  auto [points, contours] = PathTessellator::CountFillStorage(path, 1.0f);
296  EXPECT_EQ(points, 5u);
297  EXPECT_EQ(contours, 1u);
298 
299  ::testing::StrictMock<MockPathVertexWriter> mock_writer;
300  {
301  ::testing::InSequence sequence;
302 
303  EXPECT_CALL(mock_writer, Write(Point(0, 0)));
304  EXPECT_CALL(mock_writer, Write(Point(10, 10)));
305  EXPECT_CALL(mock_writer, Write(Point(20, 10)));
306  EXPECT_CALL(mock_writer, Write(Point(10, 0)));
307  EXPECT_CALL(mock_writer, Write(Point(0, 0)));
308  EXPECT_CALL(mock_writer, EndContour());
309  }
310  PathTessellator::PathToFilledVertices(path, mock_writer, 1.0f);
311 }
312 
313 TEST(PathTessellatorTest, ConicToQuadToOptimization) {
314  // The conic below will simplify to this quad
315  PathTessellator::Quad quad{{0, 0}, {10, 0}, {0, 10}};
316 
317  flutter::DlPathBuilder builder;
318  builder.MoveTo(quad.p1);
319  // weight == 1
320  builder.ConicCurveTo(quad.cp, quad.p2, 1.0f);
321  builder.Close();
322  flutter::DlPath path = builder.TakePath();
323 
324  ::testing::StrictMock<MockSegmentReceiver> mock_receiver;
325  {
326  ::testing::InSequence sequence;
327 
328  EXPECT_CALL(mock_receiver, BeginContour(quad.p1, /*will_be_closed=*/true));
329  EXPECT_CALL(mock_receiver, RecordQuad(quad.p1, quad.cp, quad.p2));
330  EXPECT_CALL(mock_receiver, RecordLine(quad.p2, quad.p1));
331  EXPECT_CALL(mock_receiver, EndContour(quad.p1, /*with_close=*/true));
332  }
333  PathTessellator::PathToFilledSegments(path, mock_receiver);
334 
335  auto [points, contours] = PathTessellator::CountFillStorage(path, 1.0f);
336  EXPECT_EQ(points, 7u);
337  EXPECT_EQ(contours, 1u);
338 
339  ::testing::StrictMock<MockPathVertexWriter> mock_writer;
340  {
341  ::testing::InSequence sequence;
342 
343  EXPECT_CALL(mock_writer, Write(quad.p1));
344  {
345  EXPECT_CALL(mock_writer, Write(quad.Solve(1 / 5.0f)));
346  EXPECT_CALL(mock_writer, Write(quad.Solve(2 / 5.0f)));
347  EXPECT_CALL(mock_writer, Write(quad.Solve(3 / 5.0f)));
348  EXPECT_CALL(mock_writer, Write(quad.Solve(4 / 5.0f)));
349  EXPECT_CALL(mock_writer, Write(quad.p2));
350  }
351  EXPECT_CALL(mock_writer, Write(quad.p1));
352  EXPECT_CALL(mock_writer, EndContour());
353  }
354  PathTessellator::PathToFilledVertices(path, mock_writer, 1.0f);
355 }
356 
357 TEST(PathTessellatorTest, SimplePathMultipleMoveTo) {
358  flutter::DlPathBuilder builder;
359  builder.MoveTo({500, 100});
360  builder.MoveTo({0, 0});
361  builder.LineTo({10, 10});
362  builder.LineTo({0, 20});
363  builder.Close();
364  flutter::DlPath path = builder.TakePath();
365 
366  ::testing::StrictMock<MockSegmentReceiver> mock_receiver;
367  {
368  ::testing::InSequence sequence;
369 
370  EXPECT_CALL(mock_receiver,
371  BeginContour(Point(0, 0), /*will_be_closed=*/true));
372  EXPECT_CALL(mock_receiver, RecordLine(Point(0, 0), Point(10, 10)));
373  EXPECT_CALL(mock_receiver, RecordLine(Point(10, 10), Point(0, 20)));
374  EXPECT_CALL(mock_receiver, RecordLine(Point(0, 20), Point(0, 0)));
375  EXPECT_CALL(mock_receiver, EndContour(Point(0, 0), /*with_close=*/true));
376  }
377  PathTessellator::PathToFilledSegments(path, mock_receiver);
378 
379  auto [points, contours] = PathTessellator::CountFillStorage(path, 1.0f);
380  EXPECT_EQ(points, 4u);
381  EXPECT_EQ(contours, 1u);
382 
383  ::testing::StrictMock<MockPathVertexWriter> mock_writer;
384  {
385  ::testing::InSequence sequence;
386 
387  EXPECT_CALL(mock_writer, Write(Point(0, 0)));
388  EXPECT_CALL(mock_writer, Write(Point(10, 10)));
389  EXPECT_CALL(mock_writer, Write(Point(0, 20)));
390  EXPECT_CALL(mock_writer, Write(Point(0, 0)));
391  EXPECT_CALL(mock_writer, EndContour());
392  }
393  PathTessellator::PathToFilledVertices(path, mock_writer, 1.0f);
394 }
395 
396 TEST(PathTessellatorTest, ComplexPath) {
397  PathTessellator::Quad quad{{10, 10}, {20, 20}, {20, 10}};
398  PathTessellator::Conic conic{{20, 10}, {30, 20}, {30, 10}, 2.0f};
399  PathTessellator::Cubic cubic{{30, 10}, {40, 20}, {40, 10}, {42, 15}};
400 
401  flutter::DlPathBuilder builder;
402  builder.MoveTo({0, 0});
403  builder.LineTo({10, 10});
404  builder.QuadraticCurveTo(quad.cp, quad.p2);
405  builder.ConicCurveTo(conic.cp, conic.p2, conic.weight);
406  builder.CubicCurveTo(cubic.cp1, cubic.cp2, cubic.p2);
407  builder.Close();
408  flutter::DlPath path = builder.TakePath();
409 
410  ::testing::StrictMock<MockSegmentReceiver> mock_receiver;
411  {
412  ::testing::InSequence sequence;
413 
414  EXPECT_CALL(mock_receiver,
415  BeginContour(Point(0, 0), /*will_be_closed=*/true));
416  EXPECT_CALL(mock_receiver, RecordLine(Point(0, 0), Point(10, 10)));
417  EXPECT_CALL(mock_receiver, RecordQuad(quad.p1, quad.cp, quad.p2));
418  EXPECT_CALL(mock_receiver,
419  RecordConic(conic.p1, conic.cp, conic.p2, conic.weight));
420  EXPECT_CALL(mock_receiver,
421  RecordCubic(cubic.p1, cubic.cp1, cubic.cp2, cubic.p2));
422  EXPECT_CALL(mock_receiver, RecordLine(cubic.p2, Point(0, 0)));
423  EXPECT_CALL(mock_receiver, EndContour(Point(0, 0), /*with_close=*/true));
424  }
425  PathTessellator::PathToFilledSegments(path, mock_receiver);
426 
427  auto [points, contours] = PathTessellator::CountFillStorage(path, 1.0f);
428  EXPECT_EQ(points, 25u);
429  EXPECT_EQ(contours, 1u);
430 
431  ::testing::StrictMock<MockPathVertexWriter> mock_writer;
432  {
433  ::testing::InSequence sequence;
434 
435  EXPECT_CALL(mock_writer, Write(Point(0, 0)));
436  EXPECT_CALL(mock_writer, Write(Point(10, 10)));
437  {
438  EXPECT_CALL(mock_writer, Write(quad.Solve(1 / 5.0f)));
439  EXPECT_CALL(mock_writer, Write(quad.Solve(2 / 5.0f)));
440  EXPECT_CALL(mock_writer, Write(quad.Solve(3 / 5.0f)));
441  EXPECT_CALL(mock_writer, Write(quad.Solve(4 / 5.0f)));
442  EXPECT_CALL(mock_writer, Write(quad.p2));
443  }
444  {
445  EXPECT_CALL(mock_writer, Write(conic.Solve(1 / 8.0f)));
446  EXPECT_CALL(mock_writer, Write(conic.Solve(2 / 8.0f)));
447  EXPECT_CALL(mock_writer, Write(conic.Solve(3 / 8.0f)));
448  EXPECT_CALL(mock_writer, Write(conic.Solve(4 / 8.0f)));
449  EXPECT_CALL(mock_writer, Write(conic.Solve(5 / 8.0f)));
450  EXPECT_CALL(mock_writer, Write(conic.Solve(6 / 8.0f)));
451  EXPECT_CALL(mock_writer, Write(conic.Solve(7 / 8.0f)));
452  EXPECT_CALL(mock_writer, Write(conic.p2));
453  }
454  {
455  EXPECT_CALL(mock_writer, Write(cubic.Solve(1 / 9.0f)));
456  EXPECT_CALL(mock_writer, Write(cubic.Solve(2 / 9.0f)));
457  EXPECT_CALL(mock_writer, Write(cubic.Solve(3 / 9.0f)));
458  EXPECT_CALL(mock_writer, Write(cubic.Solve(4 / 9.0f)));
459  EXPECT_CALL(mock_writer, Write(cubic.Solve(5 / 9.0f)));
460  EXPECT_CALL(mock_writer, Write(cubic.Solve(6 / 9.0f)));
461  EXPECT_CALL(mock_writer, Write(cubic.Solve(7 / 9.0f)));
462  EXPECT_CALL(mock_writer, Write(cubic.Solve(8 / 9.0f)));
463  EXPECT_CALL(mock_writer, Write(cubic.p2));
464  }
465  EXPECT_CALL(mock_writer, Write(Point(0, 0)));
466  EXPECT_CALL(mock_writer, EndContour());
467  }
468  PathTessellator::PathToFilledVertices(path, mock_writer, 1.0f);
469 }
470 
471 TEST(PathTessellatorTest, ComplexPathTrailingMoveTo) {
472  PathTessellator::Quad quad{{10, 10}, {20, 20}, {20, 10}};
473  PathTessellator::Conic conic{{20, 10}, {30, 20}, {30, 10}, 2.0f};
474  PathTessellator::Cubic cubic{{30, 10}, {40, 20}, {40, 10}, {42, 15}};
475 
476  flutter::DlPathBuilder builder;
477  builder.MoveTo({0, 0});
478  builder.LineTo({10, 10});
479  builder.QuadraticCurveTo(quad.cp, quad.p2);
480  builder.ConicCurveTo(conic.cp, conic.p2, conic.weight);
481  builder.CubicCurveTo(cubic.cp1, cubic.cp2, cubic.p2);
482  builder.Close();
483  builder.MoveTo({500, 100});
484  flutter::DlPath path = builder.TakePath();
485 
486  ::testing::StrictMock<MockSegmentReceiver> mock_receiver;
487  {
488  ::testing::InSequence sequence;
489 
490  EXPECT_CALL(mock_receiver,
491  BeginContour(Point(0, 0), /*will_be_closed=*/true));
492  EXPECT_CALL(mock_receiver, RecordLine(Point(0, 0), Point(10, 10)));
493  EXPECT_CALL(mock_receiver, RecordQuad(quad.p1, quad.cp, quad.p2));
494  EXPECT_CALL(mock_receiver,
495  RecordConic(conic.p1, conic.cp, conic.p2, conic.weight));
496  EXPECT_CALL(mock_receiver,
497  RecordCubic(cubic.p1, cubic.cp1, cubic.cp2, cubic.p2));
498  EXPECT_CALL(mock_receiver, RecordLine(cubic.p2, Point(0, 0)));
499  EXPECT_CALL(mock_receiver, EndContour(Point(0, 0), /*with_close=*/true));
500  }
501  PathTessellator::PathToFilledSegments(path, mock_receiver);
502 
503  auto [points, contours] = PathTessellator::CountFillStorage(path, 1.0f);
504  EXPECT_EQ(points, 25u);
505  EXPECT_EQ(contours, 1u);
506 
507  ::testing::StrictMock<MockPathVertexWriter> mock_writer;
508  {
509  ::testing::InSequence sequence;
510 
511  EXPECT_CALL(mock_writer, Write(Point(0, 0)));
512  EXPECT_CALL(mock_writer, Write(Point(10, 10)));
513  {
514  EXPECT_CALL(mock_writer, Write(quad.Solve(1 / 5.0f)));
515  EXPECT_CALL(mock_writer, Write(quad.Solve(2 / 5.0f)));
516  EXPECT_CALL(mock_writer, Write(quad.Solve(3 / 5.0f)));
517  EXPECT_CALL(mock_writer, Write(quad.Solve(4 / 5.0f)));
518  EXPECT_CALL(mock_writer, Write(quad.p2));
519  }
520  {
521  EXPECT_CALL(mock_writer, Write(conic.Solve(1 / 8.0f)));
522  EXPECT_CALL(mock_writer, Write(conic.Solve(2 / 8.0f)));
523  EXPECT_CALL(mock_writer, Write(conic.Solve(3 / 8.0f)));
524  EXPECT_CALL(mock_writer, Write(conic.Solve(4 / 8.0f)));
525  EXPECT_CALL(mock_writer, Write(conic.Solve(5 / 8.0f)));
526  EXPECT_CALL(mock_writer, Write(conic.Solve(6 / 8.0f)));
527  EXPECT_CALL(mock_writer, Write(conic.Solve(7 / 8.0f)));
528  EXPECT_CALL(mock_writer, Write(conic.p2));
529  }
530  {
531  EXPECT_CALL(mock_writer, Write(cubic.Solve(1 / 9.0f)));
532  EXPECT_CALL(mock_writer, Write(cubic.Solve(2 / 9.0f)));
533  EXPECT_CALL(mock_writer, Write(cubic.Solve(3 / 9.0f)));
534  EXPECT_CALL(mock_writer, Write(cubic.Solve(4 / 9.0f)));
535  EXPECT_CALL(mock_writer, Write(cubic.Solve(5 / 9.0f)));
536  EXPECT_CALL(mock_writer, Write(cubic.Solve(6 / 9.0f)));
537  EXPECT_CALL(mock_writer, Write(cubic.Solve(7 / 9.0f)));
538  EXPECT_CALL(mock_writer, Write(cubic.Solve(8 / 9.0f)));
539  EXPECT_CALL(mock_writer, Write(cubic.p2));
540  }
541  EXPECT_CALL(mock_writer, Write(Point(0, 0)));
542  EXPECT_CALL(mock_writer, EndContour());
543  }
544  PathTessellator::PathToFilledVertices(path, mock_writer, 1.0f);
545 }
546 
547 TEST(PathTessellatorTest, LinearQuadToPointCount) {
548  flutter::DlPathBuilder builder;
549  builder.MoveTo({316.3, 121.5});
550  builder.QuadraticCurveTo({316.4, 121.5}, {316.5, 121.5});
551  builder.Close();
552  auto path = builder.TakePath();
553 
554  auto [points, contours] = PathTessellator::CountFillStorage(path, 2.0f);
555  EXPECT_EQ(points, 3u);
556  EXPECT_EQ(contours, 1u);
557 }
558 
559 TEST(PathTessellatorTest, LinearConicToPointCount) {
560  flutter::DlPathBuilder builder;
561  builder.MoveTo({316.3, 121.5});
562  builder.ConicCurveTo({316.4, 121.5}, {316.5, 121.5}, 2.0f);
563  builder.Close();
564  auto path = builder.TakePath();
565 
566  auto [points, contours] = PathTessellator::CountFillStorage(path, 2.0f);
567  EXPECT_EQ(points, 3u);
568  EXPECT_EQ(contours, 1u);
569 }
570 
571 TEST(PathTessellatorTest, LinearCubicToPointCount) {
572  flutter::DlPathBuilder builder;
573  builder.MoveTo({316.3, 121.5});
574  builder.CubicCurveTo({316.4, 121.5}, {316.5, 121.5}, {316.6, 121.5});
575  builder.Close();
576  auto path = builder.TakePath();
577 
578  auto [points, contours] = PathTessellator::CountFillStorage(path, 2.0f);
579  EXPECT_EQ(points, 3u);
580  EXPECT_EQ(contours, 1u);
581 }
582 
583 } // namespace testing
584 } // namespace impeller
An interface for receiving pruned path segments.
virtual void RecordLine(Point p1, Point p2)=0
virtual void RecordCubic(Point p1, Point cp1, Point cp2, Point p2)=0
virtual void RecordConic(Point p1, Point cp, Point p2, Scalar weight)=0
virtual void RecordQuad(Point p1, Point cp, Point p2)=0
virtual void EndContour(Point origin, bool with_close)=0
virtual void BeginContour(Point origin, bool will_be_closed)=0
An interface for generating a multi contour polyline as a triangle strip.
virtual void Write(Point point)=0
static void PathToFilledSegments(const PathSource &source, SegmentReceiver &receiver)
static void PathToFilledVertices(const PathSource &source, VertexWriter &writer, Scalar scale)
static std::pair< size_t, size_t > CountFillStorage(const PathSource &source, Scalar scale)
MOCK_METHOD(void, Write,(Point point),(override))
MOCK_METHOD(void, EndContour,(),(override))
MOCK_METHOD(void, RecordLine,(Point p1, Point p2),(override))
MOCK_METHOD(void, RecordCubic,(Point p1, Point cp1, Point cp2, Point p2),(override))
MOCK_METHOD(void, RecordQuad,(Point p1, Point cp, Point p2),(override))
MOCK_METHOD(void, EndContour,(Point origin, bool with_close),(override))
MOCK_METHOD(void, RecordConic,(Point p1, Point cp, Point p2, Scalar weight),(override))
MOCK_METHOD(void, BeginContour,(Point origin, bool will_be_closed),(override))
TEST(AllocationSizeTest, CanCreateTypedAllocations)
float Scalar
Definition: scalar.h:19
TPoint< Scalar > Point
Definition: point.h:327
flutter::DlPath DlPath
Definition: dl_dispatcher.h:29
std::vector< Point > points
std::vector< Contour > contours