Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Functions
PathBuilderTest.cpp File Reference
#include "include/core/SkPath.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkPathTypes.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRRect.h"
#include "include/core/SkRect.h"
#include "include/core/SkScalar.h"
#include "src/base/SkRandom.h"
#include "src/core/SkPathPriv.h"
#include "tests/Test.h"
#include <cstddef>
#include <cstdint>
#include <initializer_list>
#include <string>
#include <vector>

Go to the source code of this file.

Functions

static void is_empty (skiatest::Reporter *reporter, const SkPath &p)
 
 DEF_TEST (pathbuilder, reporter)
 
 DEF_TEST (pathbuilder_filltype, reporter)
 
static bool check_points (const SkPath &path, const SkPoint expected[], size_t count)
 
 DEF_TEST (pathbuilder_missing_move, reporter)
 
 DEF_TEST (pathbuilder_addRect, reporter)
 
static bool is_eq (const SkPath &a, const SkPath &b)
 
 DEF_TEST (pathbuilder_addOval, reporter)
 
 DEF_TEST (pathbuilder_addRRect, reporter)
 
 DEF_TEST (pathbuilder_make, reporter)
 
 DEF_TEST (pathbuilder_genid, r)
 
 DEF_TEST (pathbuilder_addPolygon, reporter)
 
 DEF_TEST (pathbuilder_addPath, reporter)
 
 DEF_TEST (pathbuilder_lastmoveindex, reporter)
 
static void assertIsMoveTo (skiatest::Reporter *reporter, SkPathPriv::RangeIter *iter, SkScalar x0, SkScalar y0)
 
static void assertIsLineTo (skiatest::Reporter *reporter, SkPathPriv::RangeIter *iter, SkScalar x1, SkScalar y1)
 
static void assertIsDone (skiatest::Reporter *reporter, SkPathPriv::RangeIter *iter, SkPath *p)
 
 DEF_TEST (SkPathBuilder_lineToMoveTo, reporter)
 
 DEF_TEST (SkPathBuilder_arcToPtPtRad_invalidInputsResultInALine, reporter)
 

Function Documentation

◆ assertIsDone()

static void assertIsDone ( skiatest::Reporter reporter,
SkPathPriv::RangeIter iter,
SkPath p 
)
static

Definition at line 370 of file PathBuilderTest.cpp.

370 {
371 REPORTER_ASSERT(reporter, *iter == SkPathPriv::Iterate(*p).end(), "Iterator is not done yet");
372}
reporter
#define REPORTER_ASSERT(r, cond,...)
Definition Test.h:286
SkPath::RangeIter end()
Definition SkPathPriv.h:187

◆ assertIsLineTo()

static void assertIsLineTo ( skiatest::Reporter reporter,
SkPathPriv::RangeIter iter,
SkScalar  x1,
SkScalar  y1 
)
static

Definition at line 360 of file PathBuilderTest.cpp.

361 {
362 auto [v, pts, w] = *(*iter)++;
363 REPORTER_ASSERT(reporter, v == SkPathVerb::kLine, "%d != %d (line)",
364 (int)v, (int)SkPathVerb::kLine);
365 // pts[0] is the moveTo before this line. See pts_backset_for_verb in SkPath::RangeIter
366 REPORTER_ASSERT(reporter, pts[1].fX == x1, "X mismatch %f != %f", pts[1].fX, x1);
367 REPORTER_ASSERT(reporter, pts[1].fY == y1, "Y mismatch %f != %f", pts[1].fY, y1);
368}
@ kLine
SkPath::RawIter returns 2 points.
SkScalar w

◆ assertIsMoveTo()

static void assertIsMoveTo ( skiatest::Reporter reporter,
SkPathPriv::RangeIter iter,
SkScalar  x0,
SkScalar  y0 
)
static

Definition at line 351 of file PathBuilderTest.cpp.

352 {
353 auto [v, pts, w] = *(*iter)++;
354 REPORTER_ASSERT(reporter, v == SkPathVerb::kMove, "%d != %d (move)",
355 (int)v, (int)SkPathVerb::kMove);
356 REPORTER_ASSERT(reporter, pts[0].fX == x0, "X mismatch %f != %f", pts[0].fX, x0);
357 REPORTER_ASSERT(reporter, pts[0].fY == y0, "Y mismatch %f != %f", pts[0].fY, y0);
358}
@ kMove
SkPath::RawIter returns 1 point.

◆ check_points()

static bool check_points ( const SkPath path,
const SkPoint  expected[],
size_t  count 
)
static

Definition at line 75 of file PathBuilderTest.cpp.

75 {
76 std::vector<SkPoint> iter_pts;
77
78 for (auto [v, p, w] : SkPathPriv::Iterate(path)) {
79 switch (v) {
81 iter_pts.push_back(p[0]);
82 break;
84 iter_pts.push_back(p[1]);
85 break;
88 iter_pts.push_back(p[1]);
89 iter_pts.push_back(p[2]);
90 break;
92 iter_pts.push_back(p[1]);
93 iter_pts.push_back(p[2]);
94 iter_pts.push_back(p[3]);
95 break;
97 break;
98 }
99 }
100 if (iter_pts.size() != count) {
101 return false;
102 }
103 for (size_t i = 0; i < count; ++i) {
104 if (iter_pts[i] != expected[i]) {
105 return false;
106 }
107 }
108 return true;
109}
int count
@ kClose
SkPath::RawIter returns 0 points.
@ kCubic
SkPath::RawIter returns 4 points.
@ kConic
SkPath::RawIter returns 3 points + 1 weight.
@ kQuad
SkPath::RawIter returns 3 points.
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition switches.h:57

◆ DEF_TEST() [1/13]

DEF_TEST ( pathbuilder  ,
reporter   
)

Definition at line 32 of file PathBuilderTest.cpp.

32 {
34
35 is_empty(reporter, b.snapshot());
36 is_empty(reporter, b.detach());
37
38 b.moveTo(10, 10).lineTo(20, 20).quadTo(30, 10, 10, 20);
39
40 SkPath p0 = b.snapshot();
41 SkPath p1 = b.snapshot();
42 SkPath p2 = b.detach();
43
44 // Builders should always precompute the path's bounds, so there is no race condition later
48
49 REPORTER_ASSERT(reporter, p0.getBounds() == SkRect::MakeLTRB(10, 10, 30, 20));
51
52 REPORTER_ASSERT(reporter, p0 == p1);
53 REPORTER_ASSERT(reporter, p0 == p2);
54
55 is_empty(reporter, b.snapshot());
56 is_empty(reporter, b.detach());
57}
static void is_empty(skiatest::Reporter *reporter, const SkPath &p)
static bool HasComputedBounds(const SkPath &path)
Definition SkPathPriv.h:223
SkPath snapshot() const
Definition SkPath.h:142
int countPoints() const
Definition SkPath.cpp:525
SkPath detach()
Definition SkPath.h:147
const SkRect & getBounds() const
Definition SkPath.cpp:420
static bool b
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition SkRect.h:646

◆ DEF_TEST() [2/13]

DEF_TEST ( pathbuilder_addOval  ,
reporter   
)

Definition at line 194 of file PathBuilderTest.cpp.

194 {
195 const SkRect r = { 10, 20, 30, 40 };
196 SkRect tmp;
197
198 for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
199 for (int i = 0; i < 4; ++i) {
200 auto bp = SkPathBuilder().addOval(r, dir, i).detach();
201 SkPath p;
202 p.addOval(r, dir, i);
204 }
205 auto bp = SkPathBuilder().addOval(r, dir).detach();
206 SkPath p;
207 p.addOval(r, dir);
209
210 // test negative case -- can't have any other segments
211 bp = SkPathBuilder().addOval(r, dir).lineTo(10, 10).detach();
212 REPORTER_ASSERT(reporter, !bp.isOval(&tmp));
213 bp = SkPathBuilder().lineTo(10, 10).addOval(r, dir).detach();
214 REPORTER_ASSERT(reporter, !bp.isOval(&tmp));
215 }
216}
static bool is_eq(const SkPath &a, const SkPath &b)
SkPathBuilder & lineTo(SkPoint pt)
SkPathBuilder & addOval(const SkRect &, SkPathDirection, unsigned startIndex)

◆ DEF_TEST() [3/13]

DEF_TEST ( pathbuilder_addPath  ,
reporter   
)

Definition at line 303 of file PathBuilderTest.cpp.

303 {
304 const auto p = SkPath()
305 .moveTo(10, 10)
306 .lineTo(100, 10)
307 .quadTo(200, 100, 100, 200)
308 .close()
309 .moveTo(200, 200)
310 .cubicTo(210, 200, 210, 300, 200, 300)
311 .conicTo(150, 250, 100, 200, 1.4f);
312
313 REPORTER_ASSERT(reporter, p == SkPathBuilder().addPath(p).detach());
314}
SkPath & moveTo(SkScalar x, SkScalar y)
Definition SkPath.cpp:678
SkPath & lineTo(SkScalar x, SkScalar y)
Definition SkPath.cpp:718
SkPath & quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2)
Definition SkPath.cpp:736
SkPath & cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3)
Definition SkPath.cpp:789
SkPath & conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar w)
Definition SkPath.cpp:756
SkPath & close()
Definition SkPath.cpp:813

◆ DEF_TEST() [4/13]

DEF_TEST ( pathbuilder_addPolygon  ,
reporter   
)

Definition at line 277 of file PathBuilderTest.cpp.

277 {
278 SkPoint pts[] = {{1, 2}, {3, 4}, {5, 6}, {7, 8}};
279
280 auto addpoly = [](const SkPoint pts[], int count, bool isClosed) {
282 if (count > 0) {
283 builder.moveTo(pts[0]);
284 for (int i = 1; i < count; ++i) {
285 builder.lineTo(pts[i]);
286 }
287 if (isClosed) {
288 builder.close();
289 }
290 }
291 return builder.detach();
292 };
293
294 for (bool isClosed : {false, true}) {
295 for (size_t i = 0; i <= std::size(pts); ++i) {
296 auto path0 = SkPathBuilder().addPolygon(pts, i, isClosed).detach();
297 auto path1 = addpoly(pts, i, isClosed);
298 REPORTER_ASSERT(reporter, path0 == path1);
299 }
300 }
301}
static SkPath path1()
SkPathBuilder & addPolygon(const SkPoint pts[], int count, bool isClosed)

◆ DEF_TEST() [5/13]

DEF_TEST ( pathbuilder_addRect  ,
reporter   
)

Definition at line 128 of file PathBuilderTest.cpp.

128 {
129 const SkRect r = { 10, 20, 30, 40 };
130
131 for (int i = 0; i < 4; ++i) {
132 for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
134 b.addRect(r, dir, i);
135 auto bp = b.detach();
136
137 SkRect r2;
138 bool closed = false;
139 SkPathDirection dir2;
140 REPORTER_ASSERT(reporter, bp.isRect(&r2, &closed, &dir2));
141 REPORTER_ASSERT(reporter, r2 == r);
142 REPORTER_ASSERT(reporter, closed);
143 REPORTER_ASSERT(reporter, dir == dir2);
144
145 SkPath p;
146 p.addRect(r, dir, i);
147 REPORTER_ASSERT(reporter, p == bp);
148 }
149 }
150}
SkPathDirection
Definition SkPathTypes.h:34
SkPathBuilder & addRect(const SkRect &, SkPathDirection, unsigned startIndex)

◆ DEF_TEST() [6/13]

DEF_TEST ( pathbuilder_addRRect  ,
reporter   
)

Definition at line 218 of file PathBuilderTest.cpp.

218 {
219 const SkRRect rr = SkRRect::MakeRectXY({ 10, 20, 30, 40 }, 5, 6);
220
221 for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
222 for (int i = 0; i < 4; ++i) {
224 b.addRRect(rr, dir, i);
225 auto bp = b.detach();
226
227 SkPath p;
228 p.addRRect(rr, dir, i);
230 }
231 auto bp = SkPathBuilder().addRRect(rr, dir).detach();
232 SkPath p;
233 p.addRRect(rr, dir);
235
236 // test negative case -- can't have any other segments
237 SkRRect tmp;
238 bp = SkPathBuilder().addRRect(rr, dir).lineTo(10, 10).detach();
239 REPORTER_ASSERT(reporter, !bp.isRRect(&tmp));
240 bp = SkPathBuilder().lineTo(10, 10).addRRect(rr, dir).detach();
241 REPORTER_ASSERT(reporter, !bp.isRRect(&tmp));
242 }
243}
SkPathBuilder & addRRect(const SkRRect &, SkPathDirection, unsigned startIndex)
static SkRRect MakeRectXY(const SkRect &rect, SkScalar xRad, SkScalar yRad)
Definition SkRRect.h:180

◆ DEF_TEST() [7/13]

DEF_TEST ( pathbuilder_filltype  ,
reporter   
)

Definition at line 59 of file PathBuilderTest.cpp.

59 {
60 for (auto fillType : { SkPathFillType::kWinding,
64 SkPathBuilder b(fillType);
65
66 REPORTER_ASSERT(reporter, b.fillType() == fillType);
67
68 for (const SkPath& path : { b.snapshot(), b.detach() }) {
69 REPORTER_ASSERT(reporter, path.getFillType() == fillType);
70 is_empty(reporter, path);
71 }
72 }
73}

◆ DEF_TEST() [8/13]

DEF_TEST ( pathbuilder_genid  ,
 
)

Definition at line 265 of file PathBuilderTest.cpp.

265 {
267
268 builder.lineTo(10, 10);
269 auto p1 = builder.snapshot();
270
271 builder.lineTo(10, 20);
272 auto p2 = builder.snapshot();
273
274 REPORTER_ASSERT(r, p1.getGenerationID() != p2.getGenerationID());
275}

◆ DEF_TEST() [9/13]

DEF_TEST ( pathbuilder_lastmoveindex  ,
reporter   
)

Definition at line 321 of file PathBuilderTest.cpp.

321 {
322 const SkPoint pts[] = {
323 {0, 1}, {2, 3}, {4, 5},
324 };
325 constexpr int N = (int)std::size(pts);
326
327 for (int ctrCount = 1; ctrCount < 4; ++ctrCount) {
328 const int lastMoveToIndex = (ctrCount - 1) * N;
329
330 for (bool isClosed : {false, true}) {
331 SkPath a, b;
332
334 for (int i = 0; i < ctrCount; ++i) {
335 builder.addPolygon(pts, N, isClosed); // new-school way
336 b.addPoly(pts, N, isClosed); // old-school way
337 }
338 a = builder.detach();
339
340 // We track the last moveTo verb index, and we invert it if the last verb was a close
341 const int expected = isClosed ? ~lastMoveToIndex : lastMoveToIndex;
342 const int a_last = SkPathPriv::LastMoveToIndex(a);
343 const int b_last = SkPathPriv::LastMoveToIndex(b);
344
345 REPORTER_ASSERT(reporter, a_last == expected);
346 REPORTER_ASSERT(reporter, b_last == expected);
347 }
348 }
349}
Type::kYUV Type::kRGBA() int(0.7 *637)
#define N
Definition beziers.cpp:19
static int LastMoveToIndex(const SkPath &path)
Definition SkPathPriv.h:348
struct MyStruct a[10]

◆ DEF_TEST() [10/13]

DEF_TEST ( pathbuilder_make  ,
reporter   
)

Definition at line 245 of file PathBuilderTest.cpp.

245 {
246 constexpr int N = 100;
247 uint8_t vbs[N];
248 SkPoint pts[N];
249
250 SkRandom rand;
252 b.moveTo(0, 0);
253 pts[0] = {0, 0}; vbs[0] = (uint8_t)SkPathVerb::kMove;
254 for (int i = 1; i < N; ++i) {
255 float x = rand.nextF();
256 float y = rand.nextF();
257 b.lineTo(x, y);
258 pts[i] = {x, y}; vbs[i] = (uint8_t)SkPathVerb::kLine;
259 }
260 auto p0 = b.detach();
261 auto p1 = SkPath::Make(pts, N, vbs, N, nullptr, 0, p0.getFillType());
262 REPORTER_ASSERT(reporter, p0 == p1);
263}
SkPathBuilder & moveTo(SkPoint pt)
static SkPath Make(const SkPoint[], int pointCount, const uint8_t[], int verbCount, const SkScalar[], int conicWeightCount, SkPathFillType, bool isVolatile=false)
Definition SkPath.cpp:3501
float nextF()
Definition SkRandom.h:55
double y
double x

◆ DEF_TEST() [11/13]

DEF_TEST ( pathbuilder_missing_move  ,
reporter   
)

Definition at line 111 of file PathBuilderTest.cpp.

111 {
113
114 b.lineTo(10, 10).lineTo(20, 30);
115 const SkPoint pts0[] = {
116 {0, 0}, {10, 10}, {20, 30},
117 };
118 REPORTER_ASSERT(reporter, check_points(b.snapshot(), pts0, std::size(pts0)));
119
120 b.reset().moveTo(20, 20).lineTo(10, 10).lineTo(20, 30).close().lineTo(60, 60);
121 const SkPoint pts1[] = {
122 {20, 20}, {10, 10}, {20, 30},
123 {20, 20}, {60, 60},
124 };
125 REPORTER_ASSERT(reporter, check_points(b.snapshot(), pts1, std::size(pts1)));
126}
static bool check_points(const SkPath &path, const SkPoint expected[], size_t count)

◆ DEF_TEST() [12/13]

DEF_TEST ( SkPathBuilder_arcToPtPtRad_invalidInputsResultInALine  ,
reporter   
)

Definition at line 395 of file PathBuilderTest.cpp.

395 {
396 auto test = [&](const std::string& name, SkPoint start, SkPoint end, SkScalar radius,
397 SkPoint expectedLineTo) {
398 SkPathBuilder pb;
399 // Remember there is an implicit moveTo(0, 0) if arcTo is the first command called.
400 pb.arcTo(start, end, radius);
401 SkPath result = pb.detach();
402
403 reporter->push(name);
404 auto iter = SkPathPriv::Iterate(result).begin();
405 assertIsMoveTo(reporter, &iter, 0, 0);
406 assertIsLineTo(reporter, &iter, expectedLineTo.fX, expectedLineTo.fY);
407 assertIsDone(reporter, &iter, &result);
408 reporter->pop();
409 };
410 // From SkPathBuilder docs:
411 // Arc is contained by tangent from last SkPath point to p1, and tangent from p1 to p2. Arc
412 // is part of circle sized to radius, positioned so it touches both tangent lines.
413 // If the values cannot construct an arc, a line to the first point is constructed instead.
414 test("first point equals previous point", {0, 0}, {1, 2}, 1, {0, 0});
415 test("two points equal", {5, 7}, {5, 7}, 1, {5, 7});
416 test("radius is zero", {-3, 5}, {-7, 11}, 0, {-3, 5});
417 test("second point equals previous point", {5, 4}, {0, 0}, 1, {5, 4});
418}
#define test(name)
static void assertIsMoveTo(skiatest::Reporter *reporter, SkPathPriv::RangeIter *iter, SkScalar x0, SkScalar y0)
static void assertIsDone(skiatest::Reporter *reporter, SkPathPriv::RangeIter *iter, SkPath *p)
static void assertIsLineTo(skiatest::Reporter *reporter, SkPathPriv::RangeIter *iter, SkScalar x1, SkScalar y1)
SkPathBuilder & arcTo(const SkRect &oval, SkScalar startAngleDeg, SkScalar sweepAngleDeg, bool forceMoveTo)
float SkScalar
Definition extension.cpp:12
glong glong end
GAsyncResult * result
const char * name
Definition fuchsia.cc:50
SkPath::RangeIter begin()
Definition SkPathPriv.h:186

◆ DEF_TEST() [13/13]

DEF_TEST ( SkPathBuilder_lineToMoveTo  ,
reporter   
)

Definition at line 374 of file PathBuilderTest.cpp.

374 {
375 SkPathBuilder pb;
376 pb.moveTo(5, -1);
377 pb.moveTo(20, 3);
378 pb.lineTo(7, 11);
379 pb.lineTo(8, 12);
380 pb.moveTo(2, 3);
381 pb.lineTo(20, 30);
382
383 SkPath result = pb.detach();
384
385 auto iter = SkPathPriv::Iterate(result).begin();
386 assertIsMoveTo(reporter, &iter, 5, -1);
387 assertIsMoveTo(reporter, &iter, 20, 3);
388 assertIsLineTo(reporter, &iter, 7, 11);
389 assertIsLineTo(reporter, &iter, 8, 12);
390 assertIsMoveTo(reporter, &iter, 2, 3);
391 assertIsLineTo(reporter, &iter, 20, 30);
392 assertIsDone(reporter, &iter, &result);
393}

◆ is_empty()

static void is_empty ( skiatest::Reporter reporter,
const SkPath p 
)
static

Definition at line 27 of file PathBuilderTest.cpp.

27 {
28 REPORTER_ASSERT(reporter, p.getBounds().isEmpty());
29 REPORTER_ASSERT(reporter, p.countPoints() == 0);
30}

◆ is_eq()

static bool is_eq ( const SkPath a,
const SkPath b 
)
static

Definition at line 152 of file PathBuilderTest.cpp.

152 {
153 if (a != b) {
154 return false;
155 }
156
157 {
158 SkRect ra, rb;
159 bool is_a = a.isOval(&ra);
160 bool is_b = b.isOval(&rb);
161 if (is_a != is_b) {
162 return false;
163 }
164 if (is_a && (ra != rb)) {
165 return false;
166 }
167 }
168
169 {
170 SkRRect rra, rrb;
171 bool is_a = a.isRRect(&rra);
172 bool is_b = b.isRRect(&rrb);
173 if (is_a != is_b) {
174 return false;
175 }
176 if (is_a && (rra != rrb)) {
177 return false;
178 }
179 }
180
181 // getConvextity() should be sufficient to test, but internally we sometimes don't want
182 // to trigger computing it, so this is the stronger test for equality.
183 {
186 if (ca != cb) {
187 return false;
188 }
189 }
190
191 return true;
192}
SkPathConvexity
Definition SkPathEnums.h:13
static SkPathConvexity GetConvexityOrUnknown(const SkPath &path)
Definition SkPathPriv.h:410