1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2011 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/core/SkPathMeasure.h"
9cb93a386Sopenharmony_ci#include "src/core/SkPathPriv.h"
10cb93a386Sopenharmony_ci#include "tests/Test.h"
11cb93a386Sopenharmony_ci
12cb93a386Sopenharmony_cistatic void test_small_segment3() {
13cb93a386Sopenharmony_ci    SkPath path;
14cb93a386Sopenharmony_ci    const SkPoint pts[] = {
15cb93a386Sopenharmony_ci        { 0, 0 },
16cb93a386Sopenharmony_ci        { 100000000000.0f, 100000000000.0f }, { 0, 0 }, { 10, 10 },
17cb93a386Sopenharmony_ci        { 10, 10 }, { 0, 0 }, { 10, 10 }
18cb93a386Sopenharmony_ci    };
19cb93a386Sopenharmony_ci
20cb93a386Sopenharmony_ci    path.moveTo(pts[0]);
21cb93a386Sopenharmony_ci    for (size_t i = 1; i < SK_ARRAY_COUNT(pts); i += 3) {
22cb93a386Sopenharmony_ci        path.cubicTo(pts[i], pts[i + 1], pts[i + 2]);
23cb93a386Sopenharmony_ci    }
24cb93a386Sopenharmony_ci
25cb93a386Sopenharmony_ci    SkPathMeasure meas(path, false);
26cb93a386Sopenharmony_ci    meas.getLength();
27cb93a386Sopenharmony_ci}
28cb93a386Sopenharmony_ci
29cb93a386Sopenharmony_cistatic void test_small_segment2() {
30cb93a386Sopenharmony_ci    SkPath path;
31cb93a386Sopenharmony_ci    const SkPoint pts[] = {
32cb93a386Sopenharmony_ci        { 0, 0 },
33cb93a386Sopenharmony_ci        { 100000000000.0f, 100000000000.0f }, { 0, 0 },
34cb93a386Sopenharmony_ci        { 10, 10 }, { 0, 0 },
35cb93a386Sopenharmony_ci    };
36cb93a386Sopenharmony_ci
37cb93a386Sopenharmony_ci    path.moveTo(pts[0]);
38cb93a386Sopenharmony_ci    for (size_t i = 1; i < SK_ARRAY_COUNT(pts); i += 2) {
39cb93a386Sopenharmony_ci        path.quadTo(pts[i], pts[i + 1]);
40cb93a386Sopenharmony_ci    }
41cb93a386Sopenharmony_ci    SkPathMeasure meas(path, false);
42cb93a386Sopenharmony_ci    meas.getLength();
43cb93a386Sopenharmony_ci}
44cb93a386Sopenharmony_ci
45cb93a386Sopenharmony_cistatic void test_small_segment() {
46cb93a386Sopenharmony_ci    SkPath path;
47cb93a386Sopenharmony_ci    const SkPoint pts[] = {
48cb93a386Sopenharmony_ci        { 100000, 100000},
49cb93a386Sopenharmony_ci        // big jump between these points, makes a big segment
50cb93a386Sopenharmony_ci        { 1.0005f, 0.9999f },
51cb93a386Sopenharmony_ci        // tiny (non-zero) jump between these points
52cb93a386Sopenharmony_ci        { SK_Scalar1, SK_Scalar1 },
53cb93a386Sopenharmony_ci    };
54cb93a386Sopenharmony_ci
55cb93a386Sopenharmony_ci    path.moveTo(pts[0]);
56cb93a386Sopenharmony_ci    for (size_t i = 1; i < SK_ARRAY_COUNT(pts); ++i) {
57cb93a386Sopenharmony_ci        path.lineTo(pts[i]);
58cb93a386Sopenharmony_ci    }
59cb93a386Sopenharmony_ci    SkPathMeasure meas(path, false);
60cb93a386Sopenharmony_ci
61cb93a386Sopenharmony_ci    /*  this would assert (before a fix) because we added a segment with
62cb93a386Sopenharmony_ci        the same length as the prev segment, due to the follow (bad) pattern
63cb93a386Sopenharmony_ci
64cb93a386Sopenharmony_ci        d = distance(pts[0], pts[1]);
65cb93a386Sopenharmony_ci        distance += d;
66cb93a386Sopenharmony_ci        seg->fDistance = distance;
67cb93a386Sopenharmony_ci
68cb93a386Sopenharmony_ci        SkASSERT(d > 0);    // TRUE
69cb93a386Sopenharmony_ci        SkASSERT(seg->fDistance > prevSeg->fDistance);  // FALSE
70cb93a386Sopenharmony_ci
71cb93a386Sopenharmony_ci        This 2nd assert failes because (distance += d) didn't affect distance
72cb93a386Sopenharmony_ci        because distance >>> d.
73cb93a386Sopenharmony_ci     */
74cb93a386Sopenharmony_ci    meas.getLength();
75cb93a386Sopenharmony_ci}
76cb93a386Sopenharmony_ci
77cb93a386Sopenharmony_ciDEF_TEST(PathMeasure, reporter) {
78cb93a386Sopenharmony_ci    SkPath  path;
79cb93a386Sopenharmony_ci
80cb93a386Sopenharmony_ci    path.moveTo(0, 0);
81cb93a386Sopenharmony_ci    path.lineTo(SK_Scalar1, 0);
82cb93a386Sopenharmony_ci    path.lineTo(SK_Scalar1, SK_Scalar1);
83cb93a386Sopenharmony_ci    path.lineTo(0, SK_Scalar1);
84cb93a386Sopenharmony_ci
85cb93a386Sopenharmony_ci    SkPathMeasure   meas(path, true);
86cb93a386Sopenharmony_ci    SkScalar        length = meas.getLength();
87cb93a386Sopenharmony_ci    SkASSERT(length == SK_Scalar1*4);
88cb93a386Sopenharmony_ci
89cb93a386Sopenharmony_ci    path.reset();
90cb93a386Sopenharmony_ci    path.moveTo(0, 0);
91cb93a386Sopenharmony_ci    path.lineTo(SK_Scalar1*3, SK_Scalar1*4);
92cb93a386Sopenharmony_ci    meas.setPath(&path, false);
93cb93a386Sopenharmony_ci    length = meas.getLength();
94cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, length == SK_Scalar1*5);
95cb93a386Sopenharmony_ci
96cb93a386Sopenharmony_ci    path.reset();
97cb93a386Sopenharmony_ci    path.addCircle(0, 0, SK_Scalar1);
98cb93a386Sopenharmony_ci    meas.setPath(&path, true);
99cb93a386Sopenharmony_ci    length = meas.getLength();
100cb93a386Sopenharmony_ci//    SkDebugf("circle arc-length = %g\n", length);
101cb93a386Sopenharmony_ci
102cb93a386Sopenharmony_ci    // Test the behavior following a close not followed by a move.
103cb93a386Sopenharmony_ci    path.reset();
104cb93a386Sopenharmony_ci    path.lineTo(SK_Scalar1, 0);
105cb93a386Sopenharmony_ci    path.lineTo(SK_Scalar1, SK_Scalar1);
106cb93a386Sopenharmony_ci    path.lineTo(0, SK_Scalar1);
107cb93a386Sopenharmony_ci    path.close();
108cb93a386Sopenharmony_ci    path.lineTo(-SK_Scalar1, 0);
109cb93a386Sopenharmony_ci    meas.setPath(&path, false);
110cb93a386Sopenharmony_ci    length = meas.getLength();
111cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, length == SK_Scalar1 * 4);
112cb93a386Sopenharmony_ci    meas.nextContour();
113cb93a386Sopenharmony_ci    length = meas.getLength();
114cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, length == SK_Scalar1);
115cb93a386Sopenharmony_ci    SkPoint position;
116cb93a386Sopenharmony_ci    SkVector tangent;
117cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent));
118cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter,
119cb93a386Sopenharmony_ci        SkScalarNearlyEqual(position.fX,
120cb93a386Sopenharmony_ci                            -SK_ScalarHalf,
121cb93a386Sopenharmony_ci                            0.0001f));
122cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, position.fY == 0);
123cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, tangent.fX == -SK_Scalar1);
124cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, tangent.fY == 0);
125cb93a386Sopenharmony_ci
126cb93a386Sopenharmony_ci    // Test degenerate paths
127cb93a386Sopenharmony_ci    path.reset();
128cb93a386Sopenharmony_ci    path.moveTo(0, 0);
129cb93a386Sopenharmony_ci    path.lineTo(0, 0);
130cb93a386Sopenharmony_ci    path.lineTo(SK_Scalar1, 0);
131cb93a386Sopenharmony_ci    path.quadTo(SK_Scalar1, 0, SK_Scalar1, 0);
132cb93a386Sopenharmony_ci    path.quadTo(SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1 * 2);
133cb93a386Sopenharmony_ci    path.cubicTo(SK_Scalar1, SK_Scalar1 * 2,
134cb93a386Sopenharmony_ci                 SK_Scalar1, SK_Scalar1 * 2,
135cb93a386Sopenharmony_ci                 SK_Scalar1, SK_Scalar1 * 2);
136cb93a386Sopenharmony_ci    path.cubicTo(SK_Scalar1*2, SK_Scalar1 * 2,
137cb93a386Sopenharmony_ci                 SK_Scalar1*3, SK_Scalar1 * 2,
138cb93a386Sopenharmony_ci                 SK_Scalar1*4, SK_Scalar1 * 2);
139cb93a386Sopenharmony_ci    meas.setPath(&path, false);
140cb93a386Sopenharmony_ci    length = meas.getLength();
141cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, length == SK_Scalar1 * 6);
142cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent));
143cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter,
144cb93a386Sopenharmony_ci        SkScalarNearlyEqual(position.fX,
145cb93a386Sopenharmony_ci                            SK_ScalarHalf,
146cb93a386Sopenharmony_ci                            0.0001f));
147cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, position.fY == 0);
148cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, tangent.fX == SK_Scalar1);
149cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, tangent.fY == 0);
150cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, meas.getPosTan(2.5f, &position, &tangent));
151cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter,
152cb93a386Sopenharmony_ci        SkScalarNearlyEqual(position.fX, SK_Scalar1, 0.0001f));
153cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter,
154cb93a386Sopenharmony_ci        SkScalarNearlyEqual(position.fY, 1.5f));
155cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, tangent.fX == 0);
156cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, tangent.fY == SK_Scalar1);
157cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, meas.getPosTan(4.5f, &position, &tangent));
158cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter,
159cb93a386Sopenharmony_ci        SkScalarNearlyEqual(position.fX,
160cb93a386Sopenharmony_ci                            2.5f,
161cb93a386Sopenharmony_ci                            0.0001f));
162cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter,
163cb93a386Sopenharmony_ci        SkScalarNearlyEqual(position.fY,
164cb93a386Sopenharmony_ci                            2.0f,
165cb93a386Sopenharmony_ci                            0.0001f));
166cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, tangent.fX == SK_Scalar1);
167cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, tangent.fY == 0);
168cb93a386Sopenharmony_ci
169cb93a386Sopenharmony_ci    path.reset();
170cb93a386Sopenharmony_ci    path.moveTo(0, 0);
171cb93a386Sopenharmony_ci    path.lineTo(SK_Scalar1, 0);
172cb93a386Sopenharmony_ci    path.moveTo(SK_Scalar1, SK_Scalar1);
173cb93a386Sopenharmony_ci    path.moveTo(SK_Scalar1 * 2, SK_Scalar1 * 2);
174cb93a386Sopenharmony_ci    path.lineTo(SK_Scalar1, SK_Scalar1 * 2);
175cb93a386Sopenharmony_ci    meas.setPath(&path, false);
176cb93a386Sopenharmony_ci    length = meas.getLength();
177cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, length == SK_Scalar1);
178cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent));
179cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter,
180cb93a386Sopenharmony_ci        SkScalarNearlyEqual(position.fX,
181cb93a386Sopenharmony_ci                            SK_ScalarHalf,
182cb93a386Sopenharmony_ci                            0.0001f));
183cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, position.fY == 0);
184cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, tangent.fX == SK_Scalar1);
185cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, tangent.fY == 0);
186cb93a386Sopenharmony_ci    meas.nextContour();
187cb93a386Sopenharmony_ci    length = meas.getLength();
188cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, length == SK_Scalar1);
189cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent));
190cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter,
191cb93a386Sopenharmony_ci        SkScalarNearlyEqual(position.fX,
192cb93a386Sopenharmony_ci                            1.5f,
193cb93a386Sopenharmony_ci                            0.0001f));
194cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter,
195cb93a386Sopenharmony_ci        SkScalarNearlyEqual(position.fY,
196cb93a386Sopenharmony_ci                            2.0f,
197cb93a386Sopenharmony_ci                            0.0001f));
198cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, tangent.fX == -SK_Scalar1);
199cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, tangent.fY == 0);
200cb93a386Sopenharmony_ci
201cb93a386Sopenharmony_ci    test_small_segment();
202cb93a386Sopenharmony_ci    test_small_segment2();
203cb93a386Sopenharmony_ci    test_small_segment3();
204cb93a386Sopenharmony_ci}
205cb93a386Sopenharmony_ci
206cb93a386Sopenharmony_ciDEF_TEST(PathMeasureConic, reporter) {
207cb93a386Sopenharmony_ci    SkPoint stdP, hiP, pts[] = {{0,0}, {100,0}, {100,0}};
208cb93a386Sopenharmony_ci    SkPath p;
209cb93a386Sopenharmony_ci    p.moveTo(0, 0);
210cb93a386Sopenharmony_ci    p.conicTo(pts[1], pts[2], 1);
211cb93a386Sopenharmony_ci    SkPathMeasure stdm(p, false);
212cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, stdm.getPosTan(20, &stdP, nullptr));
213cb93a386Sopenharmony_ci    p.reset();
214cb93a386Sopenharmony_ci    p.moveTo(0, 0);
215cb93a386Sopenharmony_ci    p.conicTo(pts[1], pts[2], 10);
216cb93a386Sopenharmony_ci    stdm.setPath(&p, false);
217cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, stdm.getPosTan(20, &hiP, nullptr));
218cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 19.5f < stdP.fX && stdP.fX < 20.5f);
219cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 19.5f < hiP.fX && hiP.fX < 20.5f);
220cb93a386Sopenharmony_ci}
221cb93a386Sopenharmony_ci
222cb93a386Sopenharmony_ci// Regression test for b/26425223
223cb93a386Sopenharmony_ciDEF_TEST(PathMeasure_nextctr, reporter) {
224cb93a386Sopenharmony_ci    SkPath path;
225cb93a386Sopenharmony_ci    path.moveTo(0, 0); path.lineTo(100, 0);
226cb93a386Sopenharmony_ci
227cb93a386Sopenharmony_ci    SkPathMeasure meas(path, false);
228cb93a386Sopenharmony_ci    // only expect 1 contour, even if we didn't explicitly call getLength() ourselves
229cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, !meas.nextContour());
230cb93a386Sopenharmony_ci}
231cb93a386Sopenharmony_ci
232cb93a386Sopenharmony_ci#include "include/core/SkContourMeasure.h"
233cb93a386Sopenharmony_ci
234cb93a386Sopenharmony_cistatic void test_90_degrees(sk_sp<SkContourMeasure> cm, SkScalar radius,
235cb93a386Sopenharmony_ci                            skiatest::Reporter* reporter) {
236cb93a386Sopenharmony_ci    SkPoint pos;
237cb93a386Sopenharmony_ci    SkVector tan;
238cb93a386Sopenharmony_ci    SkScalar distance = cm->length() / 4;
239cb93a386Sopenharmony_ci    bool success = cm->getPosTan(distance, &pos, &tan);
240cb93a386Sopenharmony_ci
241cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, success);
242cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, SkScalarNearlyEqual(pos.fX, 0));
243cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, SkScalarNearlyEqual(pos.fY, radius));
244cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, SkScalarNearlyEqual(tan.fX, -1));
245cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, SkScalarNearlyEqual(tan.fY, 0));
246cb93a386Sopenharmony_ci}
247cb93a386Sopenharmony_ci
248cb93a386Sopenharmony_cistatic void test_empty_contours(skiatest::Reporter* reporter) {
249cb93a386Sopenharmony_ci    SkPath path;
250cb93a386Sopenharmony_ci
251cb93a386Sopenharmony_ci    path.moveTo(0, 0).lineTo(100, 100).lineTo(200, 100);
252cb93a386Sopenharmony_ci    path.moveTo(2, 2).moveTo(3, 3);                 // zero-length(s)
253cb93a386Sopenharmony_ci    path.moveTo(4, 4).close().close().close();      // zero-length
254cb93a386Sopenharmony_ci    path.moveTo(5, 5).lineTo(5, 5);                 // zero-length
255cb93a386Sopenharmony_ci    path.moveTo(5, 5).lineTo(5, 5).close();         // zero-length
256cb93a386Sopenharmony_ci    path.moveTo(5, 5).lineTo(5, 5).close().close(); // zero-length
257cb93a386Sopenharmony_ci    path.moveTo(6, 6).lineTo(7, 7);
258cb93a386Sopenharmony_ci    path.moveTo(10, 10);                            // zero-length
259cb93a386Sopenharmony_ci
260cb93a386Sopenharmony_ci    SkContourMeasureIter fact(path, false);
261cb93a386Sopenharmony_ci
262cb93a386Sopenharmony_ci    // given the above construction, we expect only 2 contours (the rest are "empty")
263cb93a386Sopenharmony_ci
264cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, fact.next());
265cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, fact.next());
266cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, !fact.next());
267cb93a386Sopenharmony_ci}
268cb93a386Sopenharmony_ci
269cb93a386Sopenharmony_cistatic void test_MLM_contours(skiatest::Reporter* reporter) {
270cb93a386Sopenharmony_ci    SkPath path;
271cb93a386Sopenharmony_ci
272cb93a386Sopenharmony_ci    // This odd sequence (with a trailing moveTo) used to return a 2nd contour, which is
273cb93a386Sopenharmony_ci    // wrong, since the contract for a measure is to only return non-zero length contours.
274cb93a386Sopenharmony_ci    path.moveTo(10, 10).lineTo(20, 20).moveTo(30, 30);
275cb93a386Sopenharmony_ci
276cb93a386Sopenharmony_ci    for (bool forceClosed : {false, true}) {
277cb93a386Sopenharmony_ci        SkContourMeasureIter fact(path, forceClosed);
278cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, fact.next());
279cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !fact.next());
280cb93a386Sopenharmony_ci    }
281cb93a386Sopenharmony_ci}
282cb93a386Sopenharmony_ci
283cb93a386Sopenharmony_cistatic void test_shrink(skiatest::Reporter* reporter) {
284cb93a386Sopenharmony_ci    SkPath path;
285cb93a386Sopenharmony_ci    path.addRect({1, 2, 3, 4});
286cb93a386Sopenharmony_ci    path.incReserve(100);   // give shrinkToFit() something to do
287cb93a386Sopenharmony_ci
288cb93a386Sopenharmony_ci    SkContourMeasureIter iter(path, false);
289cb93a386Sopenharmony_ci
290cb93a386Sopenharmony_ci    // shrinks the allocation, possibly relocating the underlying arrays.
291cb93a386Sopenharmony_ci    // The contouremasureiter needs to have safely copied path, to be unaffected by this
292cb93a386Sopenharmony_ci    // change to "path".
293cb93a386Sopenharmony_ci    SkPathPriv::ShrinkToFit(&path);
294cb93a386Sopenharmony_ci
295cb93a386Sopenharmony_ci    // Note, this failed (before the fix) on an ASAN build, which notices that we were
296cb93a386Sopenharmony_ci    // using an internal iterator of the passed-in path, not our copy.
297cb93a386Sopenharmony_ci    while (iter.next())
298cb93a386Sopenharmony_ci        ;
299cb93a386Sopenharmony_ci}
300cb93a386Sopenharmony_ci
301cb93a386Sopenharmony_ciDEF_TEST(contour_measure, reporter) {
302cb93a386Sopenharmony_ci    SkPath path;
303cb93a386Sopenharmony_ci    path.addCircle(0, 0, 100);
304cb93a386Sopenharmony_ci    path.addCircle(0, 0, 10);
305cb93a386Sopenharmony_ci
306cb93a386Sopenharmony_ci    SkContourMeasureIter fact(path, false);
307cb93a386Sopenharmony_ci    path.reset();   // we should not need the path avert we created the factory
308cb93a386Sopenharmony_ci
309cb93a386Sopenharmony_ci    auto cm0 = fact.next();
310cb93a386Sopenharmony_ci    auto cm1 = fact.next();
311cb93a386Sopenharmony_ci
312cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, cm0->isClosed());
313cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, SkScalarNearlyEqual(cm0->length(), 200 * SK_ScalarPI, 1.5f));
314cb93a386Sopenharmony_ci
315cb93a386Sopenharmony_ci    test_90_degrees(cm0, 100, reporter);
316cb93a386Sopenharmony_ci
317cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, cm1->isClosed());
318cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, SkScalarNearlyEqual(cm1->length(), 20 * SK_ScalarPI, 0.5f));
319cb93a386Sopenharmony_ci
320cb93a386Sopenharmony_ci    test_90_degrees(cm1, 10, reporter);
321cb93a386Sopenharmony_ci
322cb93a386Sopenharmony_ci    auto cm2 = fact.next();
323cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, !cm2);
324cb93a386Sopenharmony_ci
325cb93a386Sopenharmony_ci    test_empty_contours(reporter);
326cb93a386Sopenharmony_ci    test_MLM_contours(reporter);
327cb93a386Sopenharmony_ci
328cb93a386Sopenharmony_ci    test_shrink(reporter);
329cb93a386Sopenharmony_ci}
330