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