1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2014 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/SkPaint.h" 9cb93a386Sopenharmony_ci#include "include/core/SkPath.h" 10cb93a386Sopenharmony_ci#include "include/core/SkTime.h" 11cb93a386Sopenharmony_ci#include "include/utils/SkRandom.h" 12cb93a386Sopenharmony_ci#include "src/core/SkPointPriv.h" 13cb93a386Sopenharmony_ci#include "src/core/SkStrokerPriv.h" 14cb93a386Sopenharmony_ci#include "src/pathops/SkPathOpsCubic.h" 15cb93a386Sopenharmony_ci#include "tests/PathOpsCubicIntersectionTestData.h" 16cb93a386Sopenharmony_ci#include "tests/PathOpsQuadIntersectionTestData.h" 17cb93a386Sopenharmony_ci#include "tests/Test.h" 18cb93a386Sopenharmony_ci#include "tools/flags/CommandLineFlags.h" 19cb93a386Sopenharmony_ci 20cb93a386Sopenharmony_ciusing namespace PathOpsCubicIntersectionTestData; 21cb93a386Sopenharmony_ci 22cb93a386Sopenharmony_cistatic DEFINE_bool(timeout, true, "run until alloted time expires"); 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_ci#define MS_TEST_DURATION 10 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_ciconst SkScalar widths[] = {-FLT_MAX, -1, -0.1f, -FLT_EPSILON, 0, FLT_EPSILON, 27cb93a386Sopenharmony_ci 0.0000001f, 0.000001f, 0.00001f, 0.0001f, 0.001f, 0.01f, 28cb93a386Sopenharmony_ci 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 1, 1.1f, 2, 10, 10e2f, 10e3f, 10e4f, 10e5f, 10e6f, 10e7f, 29cb93a386Sopenharmony_ci 10e8f, 10e9f, 10e10f, 10e20f, FLT_MAX }; 30cb93a386Sopenharmony_cisize_t widths_count = SK_ARRAY_COUNT(widths); 31cb93a386Sopenharmony_ci 32cb93a386Sopenharmony_cistatic void pathTest(const SkPath& path) { 33cb93a386Sopenharmony_ci SkPaint p; 34cb93a386Sopenharmony_ci SkPath fill; 35cb93a386Sopenharmony_ci p.setStyle(SkPaint::kStroke_Style); 36cb93a386Sopenharmony_ci for (size_t index = 0; index < widths_count; ++index) { 37cb93a386Sopenharmony_ci p.setStrokeWidth(widths[index]); 38cb93a386Sopenharmony_ci p.getFillPath(path, &fill); 39cb93a386Sopenharmony_ci } 40cb93a386Sopenharmony_ci} 41cb93a386Sopenharmony_ci 42cb93a386Sopenharmony_cistatic void cubicTest(const SkPoint c[4]) { 43cb93a386Sopenharmony_ci SkPath path; 44cb93a386Sopenharmony_ci path.moveTo(c[0].fX, c[0].fY); 45cb93a386Sopenharmony_ci path.cubicTo(c[1].fX, c[1].fY, c[2].fX, c[2].fY, c[3].fX, c[3].fY); 46cb93a386Sopenharmony_ci pathTest(path); 47cb93a386Sopenharmony_ci} 48cb93a386Sopenharmony_ci 49cb93a386Sopenharmony_cistatic void quadTest(const SkPoint c[3]) { 50cb93a386Sopenharmony_ci SkPath path; 51cb93a386Sopenharmony_ci path.moveTo(c[0].fX, c[0].fY); 52cb93a386Sopenharmony_ci path.quadTo(c[1].fX, c[1].fY, c[2].fX, c[2].fY); 53cb93a386Sopenharmony_ci pathTest(path); 54cb93a386Sopenharmony_ci} 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_cistatic void cubicSetTest(const CubicPts* dCubic, size_t count) { 57cb93a386Sopenharmony_ci skiatest::Timer timer; 58cb93a386Sopenharmony_ci for (size_t index = 0; index < count; ++index) { 59cb93a386Sopenharmony_ci const CubicPts& dPts = dCubic[index]; 60cb93a386Sopenharmony_ci SkDCubic d; 61cb93a386Sopenharmony_ci d.debugSet(dPts.fPts); 62cb93a386Sopenharmony_ci SkPoint c[4] = { {(float) d[0].fX, (float) d[0].fY}, {(float) d[1].fX, (float) d[1].fY}, 63cb93a386Sopenharmony_ci {(float) d[2].fX, (float) d[2].fY}, {(float) d[3].fX, (float) d[3].fY} }; 64cb93a386Sopenharmony_ci cubicTest(c); 65cb93a386Sopenharmony_ci if (FLAGS_timeout && timer.elapsedMs() > MS_TEST_DURATION) { 66cb93a386Sopenharmony_ci return; 67cb93a386Sopenharmony_ci } 68cb93a386Sopenharmony_ci } 69cb93a386Sopenharmony_ci} 70cb93a386Sopenharmony_ci 71cb93a386Sopenharmony_cistatic void cubicPairSetTest(const CubicPts dCubic[][2], size_t count) { 72cb93a386Sopenharmony_ci skiatest::Timer timer; 73cb93a386Sopenharmony_ci for (size_t index = 0; index < count; ++index) { 74cb93a386Sopenharmony_ci for (int pair = 0; pair < 2; ++pair) { 75cb93a386Sopenharmony_ci const CubicPts& dPts = dCubic[index][pair]; 76cb93a386Sopenharmony_ci SkDCubic d; 77cb93a386Sopenharmony_ci d.debugSet(dPts.fPts); 78cb93a386Sopenharmony_ci SkPoint c[4] = { {(float) d[0].fX, (float) d[0].fY}, {(float) d[1].fX, (float) d[1].fY}, 79cb93a386Sopenharmony_ci {(float) d[2].fX, (float) d[2].fY}, {(float) d[3].fX, (float) d[3].fY} }; 80cb93a386Sopenharmony_ci cubicTest(c); 81cb93a386Sopenharmony_ci if (FLAGS_timeout && timer.elapsedMs() > MS_TEST_DURATION) { 82cb93a386Sopenharmony_ci return; 83cb93a386Sopenharmony_ci } 84cb93a386Sopenharmony_ci } 85cb93a386Sopenharmony_ci } 86cb93a386Sopenharmony_ci} 87cb93a386Sopenharmony_ci 88cb93a386Sopenharmony_cistatic void quadSetTest(const QuadPts* dQuad, size_t count) { 89cb93a386Sopenharmony_ci skiatest::Timer timer; 90cb93a386Sopenharmony_ci for (size_t index = 0; index < count; ++index) { 91cb93a386Sopenharmony_ci const QuadPts& dPts = dQuad[index]; 92cb93a386Sopenharmony_ci SkDQuad d; 93cb93a386Sopenharmony_ci d.debugSet(dPts.fPts); 94cb93a386Sopenharmony_ci SkPoint c[3] = { {(float) d[0].fX, (float) d[0].fY}, {(float) d[1].fX, (float) d[1].fY}, 95cb93a386Sopenharmony_ci {(float) d[2].fX, (float) d[2].fY} }; 96cb93a386Sopenharmony_ci quadTest(c); 97cb93a386Sopenharmony_ci if (FLAGS_timeout && timer.elapsedMs() > MS_TEST_DURATION) { 98cb93a386Sopenharmony_ci return; 99cb93a386Sopenharmony_ci } 100cb93a386Sopenharmony_ci } 101cb93a386Sopenharmony_ci} 102cb93a386Sopenharmony_ci 103cb93a386Sopenharmony_cistatic void quadPairSetTest(const QuadPts dQuad[][2], size_t count) { 104cb93a386Sopenharmony_ci skiatest::Timer timer; 105cb93a386Sopenharmony_ci for (size_t index = 0; index < count; ++index) { 106cb93a386Sopenharmony_ci for (int pair = 0; pair < 2; ++pair) { 107cb93a386Sopenharmony_ci const QuadPts& dPts = dQuad[index][pair]; 108cb93a386Sopenharmony_ci SkDQuad d; 109cb93a386Sopenharmony_ci d.debugSet(dPts.fPts); 110cb93a386Sopenharmony_ci SkPoint c[3] = { {(float) d[0].fX, (float) d[0].fY}, {(float) d[1].fX, (float) d[1].fY}, 111cb93a386Sopenharmony_ci {(float) d[2].fX, (float) d[2].fY} }; 112cb93a386Sopenharmony_ci quadTest(c); 113cb93a386Sopenharmony_ci if (FLAGS_timeout && timer.elapsedMs() > MS_TEST_DURATION) { 114cb93a386Sopenharmony_ci return; 115cb93a386Sopenharmony_ci } 116cb93a386Sopenharmony_ci } 117cb93a386Sopenharmony_ci } 118cb93a386Sopenharmony_ci} 119cb93a386Sopenharmony_ci 120cb93a386Sopenharmony_ciDEF_TEST(QuadStrokerSet, reporter) { 121cb93a386Sopenharmony_ci quadSetTest(quadraticLines, quadraticLines_count); 122cb93a386Sopenharmony_ci quadSetTest(quadraticPoints, quadraticPoints_count); 123cb93a386Sopenharmony_ci quadSetTest(quadraticModEpsilonLines, quadraticModEpsilonLines_count); 124cb93a386Sopenharmony_ci quadPairSetTest(quadraticTests, quadraticTests_count); 125cb93a386Sopenharmony_ci} 126cb93a386Sopenharmony_ci 127cb93a386Sopenharmony_ciDEF_TEST(CubicStrokerSet, reporter) { 128cb93a386Sopenharmony_ci cubicSetTest(pointDegenerates, pointDegenerates_count); 129cb93a386Sopenharmony_ci cubicSetTest(notPointDegenerates, notPointDegenerates_count); 130cb93a386Sopenharmony_ci cubicSetTest(lines, lines_count); 131cb93a386Sopenharmony_ci cubicSetTest(notLines, notLines_count); 132cb93a386Sopenharmony_ci cubicSetTest(modEpsilonLines, modEpsilonLines_count); 133cb93a386Sopenharmony_ci cubicSetTest(lessEpsilonLines, lessEpsilonLines_count); 134cb93a386Sopenharmony_ci cubicSetTest(negEpsilonLines, negEpsilonLines_count); 135cb93a386Sopenharmony_ci cubicPairSetTest(tests, tests_count); 136cb93a386Sopenharmony_ci} 137cb93a386Sopenharmony_ci 138cb93a386Sopenharmony_cistatic SkScalar unbounded(SkRandom& r) { 139cb93a386Sopenharmony_ci uint32_t val = r.nextU(); 140cb93a386Sopenharmony_ci return SkBits2Float(val); 141cb93a386Sopenharmony_ci} 142cb93a386Sopenharmony_ci 143cb93a386Sopenharmony_cistatic SkScalar unboundedPos(SkRandom& r) { 144cb93a386Sopenharmony_ci uint32_t val = r.nextU() & 0x7fffffff; 145cb93a386Sopenharmony_ci return SkBits2Float(val); 146cb93a386Sopenharmony_ci} 147cb93a386Sopenharmony_ci 148cb93a386Sopenharmony_ciDEF_TEST(QuadStrokerUnbounded, reporter) { 149cb93a386Sopenharmony_ci SkRandom r; 150cb93a386Sopenharmony_ci SkPaint p; 151cb93a386Sopenharmony_ci p.setStyle(SkPaint::kStroke_Style); 152cb93a386Sopenharmony_ci#if defined(SK_DEBUG) && QUAD_STROKE_APPROX_EXTENDED_DEBUGGING 153cb93a386Sopenharmony_ci int best = 0; 154cb93a386Sopenharmony_ci sk_bzero(gMaxRecursion, sizeof(gMaxRecursion[0]) * 3); 155cb93a386Sopenharmony_ci#endif 156cb93a386Sopenharmony_ci skiatest::Timer timer; 157cb93a386Sopenharmony_ci for (int i = 0; i < 1000000; ++i) { 158cb93a386Sopenharmony_ci SkPath path, fill; 159cb93a386Sopenharmony_ci path.moveTo(unbounded(r), unbounded(r)); 160cb93a386Sopenharmony_ci path.quadTo(unbounded(r), unbounded(r), unbounded(r), unbounded(r)); 161cb93a386Sopenharmony_ci p.setStrokeWidth(unboundedPos(r)); 162cb93a386Sopenharmony_ci p.getFillPath(path, &fill); 163cb93a386Sopenharmony_ci#if defined(SK_DEBUG) && QUAD_STROKE_APPROX_EXTENDED_DEBUGGING 164cb93a386Sopenharmony_ci if (best < gMaxRecursion[2]) { 165cb93a386Sopenharmony_ci if (reporter->verbose()) { 166cb93a386Sopenharmony_ci SkDebugf("\n%s quad=%d width=%1.9g\n", __FUNCTION__, gMaxRecursion[2], 167cb93a386Sopenharmony_ci p.getStrokeWidth()); 168cb93a386Sopenharmony_ci path.dumpHex(); 169cb93a386Sopenharmony_ci SkDebugf("fill:\n"); 170cb93a386Sopenharmony_ci fill.dumpHex(); 171cb93a386Sopenharmony_ci } 172cb93a386Sopenharmony_ci best = gMaxRecursion[2]; 173cb93a386Sopenharmony_ci } 174cb93a386Sopenharmony_ci#endif 175cb93a386Sopenharmony_ci if (FLAGS_timeout && timer.elapsedMs() > MS_TEST_DURATION) { 176cb93a386Sopenharmony_ci return; 177cb93a386Sopenharmony_ci } 178cb93a386Sopenharmony_ci } 179cb93a386Sopenharmony_ci#if defined(SK_DEBUG) && QUAD_STROKE_APPROX_EXTENDED_DEBUGGING 180cb93a386Sopenharmony_ci if (reporter->verbose()) { 181cb93a386Sopenharmony_ci SkDebugf("\n%s max quad=%d\n", __FUNCTION__, best); 182cb93a386Sopenharmony_ci } 183cb93a386Sopenharmony_ci#endif 184cb93a386Sopenharmony_ci} 185cb93a386Sopenharmony_ci 186cb93a386Sopenharmony_ciDEF_TEST(CubicStrokerUnbounded, reporter) { 187cb93a386Sopenharmony_ci SkRandom r; 188cb93a386Sopenharmony_ci SkPaint p; 189cb93a386Sopenharmony_ci p.setStyle(SkPaint::kStroke_Style); 190cb93a386Sopenharmony_ci#if defined(SK_DEBUG) && QUAD_STROKE_APPROX_EXTENDED_DEBUGGING 191cb93a386Sopenharmony_ci int bestTan = 0; 192cb93a386Sopenharmony_ci int bestCubic = 0; 193cb93a386Sopenharmony_ci sk_bzero(gMaxRecursion, sizeof(gMaxRecursion[0]) * 3); 194cb93a386Sopenharmony_ci#endif 195cb93a386Sopenharmony_ci skiatest::Timer timer; 196cb93a386Sopenharmony_ci for (int i = 0; i < 1000000; ++i) { 197cb93a386Sopenharmony_ci SkPath path, fill; 198cb93a386Sopenharmony_ci path.moveTo(unbounded(r), unbounded(r)); 199cb93a386Sopenharmony_ci path.cubicTo(unbounded(r), unbounded(r), unbounded(r), unbounded(r), 200cb93a386Sopenharmony_ci unbounded(r), unbounded(r)); 201cb93a386Sopenharmony_ci p.setStrokeWidth(unboundedPos(r)); 202cb93a386Sopenharmony_ci p.getFillPath(path, &fill); 203cb93a386Sopenharmony_ci #if defined(SK_DEBUG) && QUAD_STROKE_APPROX_EXTENDED_DEBUGGING 204cb93a386Sopenharmony_ci if (bestTan < gMaxRecursion[0] || bestCubic < gMaxRecursion[1]) { 205cb93a386Sopenharmony_ci if (reporter->verbose()) { 206cb93a386Sopenharmony_ci SkDebugf("\n%s tan=%d cubic=%d width=%1.9g\n", __FUNCTION__, gMaxRecursion[0], 207cb93a386Sopenharmony_ci gMaxRecursion[1], p.getStrokeWidth()); 208cb93a386Sopenharmony_ci path.dumpHex(); 209cb93a386Sopenharmony_ci SkDebugf("fill:\n"); 210cb93a386Sopenharmony_ci fill.dumpHex(); 211cb93a386Sopenharmony_ci } 212cb93a386Sopenharmony_ci bestTan = std::max(bestTan, gMaxRecursion[0]); 213cb93a386Sopenharmony_ci bestCubic = std::max(bestCubic, gMaxRecursion[1]); 214cb93a386Sopenharmony_ci } 215cb93a386Sopenharmony_ci #endif 216cb93a386Sopenharmony_ci if (FLAGS_timeout && timer.elapsedMs() > MS_TEST_DURATION) { 217cb93a386Sopenharmony_ci return; 218cb93a386Sopenharmony_ci } 219cb93a386Sopenharmony_ci } 220cb93a386Sopenharmony_ci#if defined(SK_DEBUG) && QUAD_STROKE_APPROX_EXTENDED_DEBUGGING 221cb93a386Sopenharmony_ci if (reporter->verbose()) { 222cb93a386Sopenharmony_ci SkDebugf("\n%s max tan=%d cubic=%d\n", __FUNCTION__, bestTan, bestCubic); 223cb93a386Sopenharmony_ci } 224cb93a386Sopenharmony_ci#endif 225cb93a386Sopenharmony_ci} 226cb93a386Sopenharmony_ci 227cb93a386Sopenharmony_ciDEF_TEST(QuadStrokerConstrained, reporter) { 228cb93a386Sopenharmony_ci SkRandom r; 229cb93a386Sopenharmony_ci SkPaint p; 230cb93a386Sopenharmony_ci p.setStyle(SkPaint::kStroke_Style); 231cb93a386Sopenharmony_ci#if defined(SK_DEBUG) && QUAD_STROKE_APPROX_EXTENDED_DEBUGGING 232cb93a386Sopenharmony_ci int best = 0; 233cb93a386Sopenharmony_ci sk_bzero(gMaxRecursion, sizeof(gMaxRecursion[0]) * 3); 234cb93a386Sopenharmony_ci#endif 235cb93a386Sopenharmony_ci skiatest::Timer timer; 236cb93a386Sopenharmony_ci for (int i = 0; i < 1000000; ++i) { 237cb93a386Sopenharmony_ci SkPath path, fill; 238cb93a386Sopenharmony_ci SkPoint quad[3]; 239cb93a386Sopenharmony_ci quad[0].fX = r.nextRangeF(0, 500); 240cb93a386Sopenharmony_ci quad[0].fY = r.nextRangeF(0, 500); 241cb93a386Sopenharmony_ci const SkScalar halfSquared = 0.5f * 0.5f; 242cb93a386Sopenharmony_ci do { 243cb93a386Sopenharmony_ci quad[1].fX = r.nextRangeF(0, 500); 244cb93a386Sopenharmony_ci quad[1].fY = r.nextRangeF(0, 500); 245cb93a386Sopenharmony_ci } while (SkPointPriv::DistanceToSqd(quad[0], quad[1]) < halfSquared); 246cb93a386Sopenharmony_ci do { 247cb93a386Sopenharmony_ci quad[2].fX = r.nextRangeF(0, 500); 248cb93a386Sopenharmony_ci quad[2].fY = r.nextRangeF(0, 500); 249cb93a386Sopenharmony_ci } while (SkPointPriv::DistanceToSqd(quad[0], quad[2]) < halfSquared 250cb93a386Sopenharmony_ci || SkPointPriv::DistanceToSqd(quad[1], quad[2]) < halfSquared); 251cb93a386Sopenharmony_ci path.moveTo(quad[0].fX, quad[0].fY); 252cb93a386Sopenharmony_ci path.quadTo(quad[1].fX, quad[1].fY, quad[2].fX, quad[2].fY); 253cb93a386Sopenharmony_ci p.setStrokeWidth(r.nextRangeF(0, 500)); 254cb93a386Sopenharmony_ci p.getFillPath(path, &fill); 255cb93a386Sopenharmony_ci#if defined(SK_DEBUG) && QUAD_STROKE_APPROX_EXTENDED_DEBUGGING 256cb93a386Sopenharmony_ci if (best < gMaxRecursion[2]) { 257cb93a386Sopenharmony_ci if (reporter->verbose()) { 258cb93a386Sopenharmony_ci SkDebugf("\n%s quad=%d width=%1.9g\n", __FUNCTION__, gMaxRecursion[2], 259cb93a386Sopenharmony_ci p.getStrokeWidth()); 260cb93a386Sopenharmony_ci path.dumpHex(); 261cb93a386Sopenharmony_ci SkDebugf("fill:\n"); 262cb93a386Sopenharmony_ci fill.dumpHex(); 263cb93a386Sopenharmony_ci } 264cb93a386Sopenharmony_ci best = gMaxRecursion[2]; 265cb93a386Sopenharmony_ci } 266cb93a386Sopenharmony_ci#endif 267cb93a386Sopenharmony_ci if (FLAGS_timeout && timer.elapsedMs() > MS_TEST_DURATION) { 268cb93a386Sopenharmony_ci return; 269cb93a386Sopenharmony_ci } 270cb93a386Sopenharmony_ci } 271cb93a386Sopenharmony_ci#if defined(SK_DEBUG) && QUAD_STROKE_APPROX_EXTENDED_DEBUGGING 272cb93a386Sopenharmony_ci if (reporter->verbose()) { 273cb93a386Sopenharmony_ci SkDebugf("\n%s max quad=%d\n", __FUNCTION__, best); 274cb93a386Sopenharmony_ci } 275cb93a386Sopenharmony_ci#endif 276cb93a386Sopenharmony_ci} 277cb93a386Sopenharmony_ci 278cb93a386Sopenharmony_ciDEF_TEST(CubicStrokerConstrained, reporter) { 279cb93a386Sopenharmony_ci SkRandom r; 280cb93a386Sopenharmony_ci SkPaint p; 281cb93a386Sopenharmony_ci p.setStyle(SkPaint::kStroke_Style); 282cb93a386Sopenharmony_ci#if defined(SK_DEBUG) && QUAD_STROKE_APPROX_EXTENDED_DEBUGGING 283cb93a386Sopenharmony_ci int bestTan = 0; 284cb93a386Sopenharmony_ci int bestCubic = 0; 285cb93a386Sopenharmony_ci sk_bzero(gMaxRecursion, sizeof(gMaxRecursion[0]) * 3); 286cb93a386Sopenharmony_ci#endif 287cb93a386Sopenharmony_ci skiatest::Timer timer; 288cb93a386Sopenharmony_ci for (int i = 0; i < 1000000; ++i) { 289cb93a386Sopenharmony_ci SkPath path, fill; 290cb93a386Sopenharmony_ci SkPoint cubic[4]; 291cb93a386Sopenharmony_ci cubic[0].fX = r.nextRangeF(0, 500); 292cb93a386Sopenharmony_ci cubic[0].fY = r.nextRangeF(0, 500); 293cb93a386Sopenharmony_ci const SkScalar halfSquared = 0.5f * 0.5f; 294cb93a386Sopenharmony_ci do { 295cb93a386Sopenharmony_ci cubic[1].fX = r.nextRangeF(0, 500); 296cb93a386Sopenharmony_ci cubic[1].fY = r.nextRangeF(0, 500); 297cb93a386Sopenharmony_ci } while (SkPointPriv::DistanceToSqd(cubic[0], cubic[1]) < halfSquared); 298cb93a386Sopenharmony_ci do { 299cb93a386Sopenharmony_ci cubic[2].fX = r.nextRangeF(0, 500); 300cb93a386Sopenharmony_ci cubic[2].fY = r.nextRangeF(0, 500); 301cb93a386Sopenharmony_ci } while ( SkPointPriv::DistanceToSqd(cubic[0], cubic[2]) < halfSquared 302cb93a386Sopenharmony_ci || SkPointPriv::DistanceToSqd(cubic[1], cubic[2]) < halfSquared); 303cb93a386Sopenharmony_ci do { 304cb93a386Sopenharmony_ci cubic[3].fX = r.nextRangeF(0, 500); 305cb93a386Sopenharmony_ci cubic[3].fY = r.nextRangeF(0, 500); 306cb93a386Sopenharmony_ci } while ( SkPointPriv::DistanceToSqd(cubic[0], cubic[3]) < halfSquared 307cb93a386Sopenharmony_ci || SkPointPriv::DistanceToSqd(cubic[1], cubic[3]) < halfSquared 308cb93a386Sopenharmony_ci || SkPointPriv::DistanceToSqd(cubic[2], cubic[3]) < halfSquared); 309cb93a386Sopenharmony_ci path.moveTo(cubic[0].fX, cubic[0].fY); 310cb93a386Sopenharmony_ci path.cubicTo(cubic[1].fX, cubic[1].fY, cubic[2].fX, cubic[2].fY, cubic[3].fX, cubic[3].fY); 311cb93a386Sopenharmony_ci p.setStrokeWidth(r.nextRangeF(0, 500)); 312cb93a386Sopenharmony_ci p.getFillPath(path, &fill); 313cb93a386Sopenharmony_ci#if defined(SK_DEBUG) && QUAD_STROKE_APPROX_EXTENDED_DEBUGGING 314cb93a386Sopenharmony_ci if (bestTan < gMaxRecursion[0] || bestCubic < gMaxRecursion[1]) { 315cb93a386Sopenharmony_ci if (reporter->verbose()) { 316cb93a386Sopenharmony_ci SkDebugf("\n%s tan=%d cubic=%d width=%1.9g\n", __FUNCTION__, gMaxRecursion[0], 317cb93a386Sopenharmony_ci gMaxRecursion[1], p.getStrokeWidth()); 318cb93a386Sopenharmony_ci path.dumpHex(); 319cb93a386Sopenharmony_ci SkDebugf("fill:\n"); 320cb93a386Sopenharmony_ci fill.dumpHex(); 321cb93a386Sopenharmony_ci } 322cb93a386Sopenharmony_ci bestTan = std::max(bestTan, gMaxRecursion[0]); 323cb93a386Sopenharmony_ci bestCubic = std::max(bestCubic, gMaxRecursion[1]); 324cb93a386Sopenharmony_ci } 325cb93a386Sopenharmony_ci#endif 326cb93a386Sopenharmony_ci if (FLAGS_timeout && timer.elapsedMs() > MS_TEST_DURATION) { 327cb93a386Sopenharmony_ci return; 328cb93a386Sopenharmony_ci } 329cb93a386Sopenharmony_ci } 330cb93a386Sopenharmony_ci#if defined(SK_DEBUG) && QUAD_STROKE_APPROX_EXTENDED_DEBUGGING 331cb93a386Sopenharmony_ci if (reporter->verbose()) { 332cb93a386Sopenharmony_ci SkDebugf("\n%s max tan=%d cubic=%d\n", __FUNCTION__, bestTan, bestCubic); 333cb93a386Sopenharmony_ci } 334cb93a386Sopenharmony_ci#endif 335cb93a386Sopenharmony_ci} 336cb93a386Sopenharmony_ci 337cb93a386Sopenharmony_ciDEF_TEST(QuadStrokerRange, reporter) { 338cb93a386Sopenharmony_ci SkRandom r; 339cb93a386Sopenharmony_ci SkPaint p; 340cb93a386Sopenharmony_ci p.setStyle(SkPaint::kStroke_Style); 341cb93a386Sopenharmony_ci#if defined(SK_DEBUG) && QUAD_STROKE_APPROX_EXTENDED_DEBUGGING 342cb93a386Sopenharmony_ci int best = 0; 343cb93a386Sopenharmony_ci sk_bzero(gMaxRecursion, sizeof(gMaxRecursion[0]) * 3); 344cb93a386Sopenharmony_ci#endif 345cb93a386Sopenharmony_ci skiatest::Timer timer; 346cb93a386Sopenharmony_ci for (int i = 0; i < 1000000; ++i) { 347cb93a386Sopenharmony_ci SkPath path, fill; 348cb93a386Sopenharmony_ci SkPoint quad[3]; 349cb93a386Sopenharmony_ci quad[0].fX = r.nextRangeF(0, 500); 350cb93a386Sopenharmony_ci quad[0].fY = r.nextRangeF(0, 500); 351cb93a386Sopenharmony_ci quad[1].fX = r.nextRangeF(0, 500); 352cb93a386Sopenharmony_ci quad[1].fY = r.nextRangeF(0, 500); 353cb93a386Sopenharmony_ci quad[2].fX = r.nextRangeF(0, 500); 354cb93a386Sopenharmony_ci quad[2].fY = r.nextRangeF(0, 500); 355cb93a386Sopenharmony_ci path.moveTo(quad[0].fX, quad[0].fY); 356cb93a386Sopenharmony_ci path.quadTo(quad[1].fX, quad[1].fY, quad[2].fX, quad[2].fY); 357cb93a386Sopenharmony_ci p.setStrokeWidth(r.nextRangeF(0, 500)); 358cb93a386Sopenharmony_ci p.getFillPath(path, &fill); 359cb93a386Sopenharmony_ci#if defined(SK_DEBUG) && QUAD_STROKE_APPROX_EXTENDED_DEBUGGING 360cb93a386Sopenharmony_ci if (best < gMaxRecursion[2]) { 361cb93a386Sopenharmony_ci if (reporter->verbose()) { 362cb93a386Sopenharmony_ci SkDebugf("\n%s quad=%d width=%1.9g\n", __FUNCTION__, gMaxRecursion[2], 363cb93a386Sopenharmony_ci p.getStrokeWidth()); 364cb93a386Sopenharmony_ci path.dumpHex(); 365cb93a386Sopenharmony_ci SkDebugf("fill:\n"); 366cb93a386Sopenharmony_ci fill.dumpHex(); 367cb93a386Sopenharmony_ci } 368cb93a386Sopenharmony_ci best = gMaxRecursion[2]; 369cb93a386Sopenharmony_ci } 370cb93a386Sopenharmony_ci#endif 371cb93a386Sopenharmony_ci if (FLAGS_timeout && timer.elapsedMs() > MS_TEST_DURATION) { 372cb93a386Sopenharmony_ci return; 373cb93a386Sopenharmony_ci } 374cb93a386Sopenharmony_ci } 375cb93a386Sopenharmony_ci#if defined(SK_DEBUG) && QUAD_STROKE_APPROX_EXTENDED_DEBUGGING 376cb93a386Sopenharmony_ci if (reporter->verbose()) { 377cb93a386Sopenharmony_ci SkDebugf("\n%s max quad=%d\n", __FUNCTION__, best); 378cb93a386Sopenharmony_ci } 379cb93a386Sopenharmony_ci#endif 380cb93a386Sopenharmony_ci} 381cb93a386Sopenharmony_ci 382cb93a386Sopenharmony_ciDEF_TEST(CubicStrokerRange, reporter) { 383cb93a386Sopenharmony_ci SkRandom r; 384cb93a386Sopenharmony_ci SkPaint p; 385cb93a386Sopenharmony_ci p.setStyle(SkPaint::kStroke_Style); 386cb93a386Sopenharmony_ci#if defined(SK_DEBUG) && QUAD_STROKE_APPROX_EXTENDED_DEBUGGING 387cb93a386Sopenharmony_ci int best[2] = { 0 }; 388cb93a386Sopenharmony_ci sk_bzero(gMaxRecursion, sizeof(gMaxRecursion[0]) * 3); 389cb93a386Sopenharmony_ci#endif 390cb93a386Sopenharmony_ci skiatest::Timer timer; 391cb93a386Sopenharmony_ci for (int i = 0; i < 1000000; ++i) { 392cb93a386Sopenharmony_ci SkPath path, fill; 393cb93a386Sopenharmony_ci path.moveTo(r.nextRangeF(0, 500), r.nextRangeF(0, 500)); 394cb93a386Sopenharmony_ci path.cubicTo(r.nextRangeF(0, 500), r.nextRangeF(0, 500), r.nextRangeF(0, 500), 395cb93a386Sopenharmony_ci r.nextRangeF(0, 500), r.nextRangeF(0, 500), r.nextRangeF(0, 500)); 396cb93a386Sopenharmony_ci p.setStrokeWidth(r.nextRangeF(0, 100)); 397cb93a386Sopenharmony_ci p.getFillPath(path, &fill); 398cb93a386Sopenharmony_ci#if defined(SK_DEBUG) && QUAD_STROKE_APPROX_EXTENDED_DEBUGGING 399cb93a386Sopenharmony_ci if (best[0] < gMaxRecursion[0] || best[1] < gMaxRecursion[1]) { 400cb93a386Sopenharmony_ci if (reporter->verbose()) { 401cb93a386Sopenharmony_ci SkDebugf("\n%s tan=%d cubic=%d width=%1.9g\n", __FUNCTION__, gMaxRecursion[0], 402cb93a386Sopenharmony_ci gMaxRecursion[1], p.getStrokeWidth()); 403cb93a386Sopenharmony_ci path.dumpHex(); 404cb93a386Sopenharmony_ci SkDebugf("fill:\n"); 405cb93a386Sopenharmony_ci fill.dumpHex(); 406cb93a386Sopenharmony_ci } 407cb93a386Sopenharmony_ci best[0] = std::max(best[0], gMaxRecursion[0]); 408cb93a386Sopenharmony_ci best[1] = std::max(best[1], gMaxRecursion[1]); 409cb93a386Sopenharmony_ci } 410cb93a386Sopenharmony_ci#endif 411cb93a386Sopenharmony_ci if (FLAGS_timeout && timer.elapsedMs() > MS_TEST_DURATION) { 412cb93a386Sopenharmony_ci return; 413cb93a386Sopenharmony_ci } 414cb93a386Sopenharmony_ci } 415cb93a386Sopenharmony_ci#if defined(SK_DEBUG) && QUAD_STROKE_APPROX_EXTENDED_DEBUGGING 416cb93a386Sopenharmony_ci if (reporter->verbose()) { 417cb93a386Sopenharmony_ci SkDebugf("\n%s max tan=%d cubic=%d\n", __FUNCTION__, best[0], best[1]); 418cb93a386Sopenharmony_ci } 419cb93a386Sopenharmony_ci#endif 420cb93a386Sopenharmony_ci} 421cb93a386Sopenharmony_ci 422cb93a386Sopenharmony_ci 423cb93a386Sopenharmony_ciDEF_TEST(QuadStrokerOneOff, reporter) { 424cb93a386Sopenharmony_ci#if defined(SK_DEBUG) && QUAD_STROKE_APPROX_EXTENDED_DEBUGGING 425cb93a386Sopenharmony_ci sk_bzero(gMaxRecursion, sizeof(gMaxRecursion[0]) * 3); 426cb93a386Sopenharmony_ci#endif 427cb93a386Sopenharmony_ci SkPaint p; 428cb93a386Sopenharmony_ci p.setStyle(SkPaint::kStroke_Style); 429cb93a386Sopenharmony_ci p.setStrokeWidth(SkDoubleToScalar(164.683548)); 430cb93a386Sopenharmony_ci 431cb93a386Sopenharmony_ci SkPath path, fill; 432cb93a386Sopenharmony_cipath.moveTo(SkBits2Float(0x43c99223), SkBits2Float(0x42b7417e)); 433cb93a386Sopenharmony_cipath.quadTo(SkBits2Float(0x4285d839), SkBits2Float(0x43ed6645), SkBits2Float(0x43c941c8), SkBits2Float(0x42b3ace3)); 434cb93a386Sopenharmony_ci p.getFillPath(path, &fill); 435cb93a386Sopenharmony_ci if (reporter->verbose()) { 436cb93a386Sopenharmony_ci SkDebugf("\n%s path\n", __FUNCTION__); 437cb93a386Sopenharmony_ci path.dump(); 438cb93a386Sopenharmony_ci SkDebugf("fill:\n"); 439cb93a386Sopenharmony_ci fill.dump(); 440cb93a386Sopenharmony_ci } 441cb93a386Sopenharmony_ci#if defined(SK_DEBUG) && QUAD_STROKE_APPROX_EXTENDED_DEBUGGING 442cb93a386Sopenharmony_ci if (reporter->verbose()) { 443cb93a386Sopenharmony_ci SkDebugf("max quad=%d\n", gMaxRecursion[2]); 444cb93a386Sopenharmony_ci } 445cb93a386Sopenharmony_ci#endif 446cb93a386Sopenharmony_ci} 447cb93a386Sopenharmony_ci 448cb93a386Sopenharmony_ciDEF_TEST(CubicStrokerOneOff, reporter) { 449cb93a386Sopenharmony_ci#if defined(SK_DEBUG) && QUAD_STROKE_APPROX_EXTENDED_DEBUGGING 450cb93a386Sopenharmony_ci sk_bzero(gMaxRecursion, sizeof(gMaxRecursion[0]) * 3); 451cb93a386Sopenharmony_ci#endif 452cb93a386Sopenharmony_ci SkPaint p; 453cb93a386Sopenharmony_ci p.setStyle(SkPaint::kStroke_Style); 454cb93a386Sopenharmony_ci p.setStrokeWidth(SkDoubleToScalar(42.835968)); 455cb93a386Sopenharmony_ci 456cb93a386Sopenharmony_ci SkPath path, fill; 457cb93a386Sopenharmony_cipath.moveTo(SkBits2Float(0x433f5370), SkBits2Float(0x43d1f4b3)); 458cb93a386Sopenharmony_cipath.cubicTo(SkBits2Float(0x4331cb76), SkBits2Float(0x43ea3340), SkBits2Float(0x4388f498), SkBits2Float(0x42f7f08d), SkBits2Float(0x43f1cd32), SkBits2Float(0x42802ec1)); 459cb93a386Sopenharmony_ci p.getFillPath(path, &fill); 460cb93a386Sopenharmony_ci if (reporter->verbose()) { 461cb93a386Sopenharmony_ci SkDebugf("\n%s path\n", __FUNCTION__); 462cb93a386Sopenharmony_ci path.dump(); 463cb93a386Sopenharmony_ci SkDebugf("fill:\n"); 464cb93a386Sopenharmony_ci fill.dump(); 465cb93a386Sopenharmony_ci } 466cb93a386Sopenharmony_ci#if defined(SK_DEBUG) && QUAD_STROKE_APPROX_EXTENDED_DEBUGGING 467cb93a386Sopenharmony_ci if (reporter->verbose()) { 468cb93a386Sopenharmony_ci SkDebugf("max tan=%d cubic=%d\n", gMaxRecursion[0], gMaxRecursion[1]); 469cb93a386Sopenharmony_ci } 470cb93a386Sopenharmony_ci#endif 471cb93a386Sopenharmony_ci} 472