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