blob: 7b9a3400fddc8ba165f18edf187d51111aae4ab1 [file] [log] [blame]
benjaminwagnerec4d4d72016-03-25 12:59:53 -07001/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
caryclarkfeff7d22014-10-09 05:36:03 -07008#include "PathOpsCubicIntersectionTestData.h"
9#include "PathOpsQuadIntersectionTestData.h"
10#include "SkCommonFlags.h"
caryclarka35ab3e2016-10-20 08:32:18 -070011#include "SkPathOpsCubic.h"
caryclarkfeff7d22014-10-09 05:36:03 -070012#include "SkPaint.h"
13#include "SkPath.h"
14#include "SkRandom.h"
15#include "SkStrokerPriv.h"
16#include "SkTime.h"
17#include "Test.h"
18
caryclark99d59152014-10-09 07:08:59 -070019DEFINE_bool(timeout, true, "run until alloted time expires");
caryclarkfeff7d22014-10-09 05:36:03 -070020
21#define MS_TEST_DURATION 10
22
23const SkScalar widths[] = {-FLT_MAX, -1, -0.1f, -FLT_EPSILON, 0, FLT_EPSILON,
24 0.0000001f, 0.000001f, 0.00001f, 0.0001f, 0.001f, 0.01f,
25 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 1, 1.1f, 2, 10, 10e2f, 10e3f, 10e4f, 10e5f, 10e6f, 10e7f,
26 10e8f, 10e9f, 10e10f, 10e20f, FLT_MAX };
27size_t widths_count = SK_ARRAY_COUNT(widths);
28
29static void pathTest(const SkPath& path) {
30 SkPaint p;
benjaminwagnerec4d4d72016-03-25 12:59:53 -070031 SkPath fill;
caryclarkfeff7d22014-10-09 05:36:03 -070032 p.setStyle(SkPaint::kStroke_Style);
33 for (size_t index = 0; index < widths_count; ++index) {
34 p.setStrokeWidth(widths[index]);
35 p.getFillPath(path, &fill);
36 }
37}
38
39static void cubicTest(const SkPoint c[4]) {
benjaminwagnerec4d4d72016-03-25 12:59:53 -070040 SkPath path;
41 path.moveTo(c[0].fX, c[0].fY);
42 path.cubicTo(c[1].fX, c[1].fY, c[2].fX, c[2].fY, c[3].fX, c[3].fY);
43 pathTest(path);
caryclarkfeff7d22014-10-09 05:36:03 -070044}
45
46static void quadTest(const SkPoint c[3]) {
benjaminwagnerec4d4d72016-03-25 12:59:53 -070047 SkPath path;
48 path.moveTo(c[0].fX, c[0].fY);
49 path.quadTo(c[1].fX, c[1].fY, c[2].fX, c[2].fY);
50 pathTest(path);
caryclarkfeff7d22014-10-09 05:36:03 -070051}
52
caryclarka35ab3e2016-10-20 08:32:18 -070053static void cubicSetTest(const CubicPts* dCubic, size_t count) {
benjaminwagnerec4d4d72016-03-25 12:59:53 -070054 skiatest::Timer timer;
55 for (size_t index = 0; index < count; ++index) {
caryclarka35ab3e2016-10-20 08:32:18 -070056 const CubicPts& dPts = dCubic[index];
57 SkDCubic d;
58 d.debugSet(dPts.fPts);
benjaminwagnerec4d4d72016-03-25 12:59:53 -070059 SkPoint c[4] = { {(float) d[0].fX, (float) d[0].fY}, {(float) d[1].fX, (float) d[1].fY},
caryclarkfeff7d22014-10-09 05:36:03 -070060 {(float) d[2].fX, (float) d[2].fY}, {(float) d[3].fX, (float) d[3].fY} };
benjaminwagnerec4d4d72016-03-25 12:59:53 -070061 cubicTest(c);
62 if (FLAGS_timeout && timer.elapsedMs() > MS_TEST_DURATION) {
caryclarkfeff7d22014-10-09 05:36:03 -070063 return;
64 }
benjaminwagnerec4d4d72016-03-25 12:59:53 -070065 }
caryclarkfeff7d22014-10-09 05:36:03 -070066}
67
caryclarka35ab3e2016-10-20 08:32:18 -070068static void cubicPairSetTest(const CubicPts dCubic[][2], size_t count) {
benjaminwagnerec4d4d72016-03-25 12:59:53 -070069 skiatest::Timer timer;
70 for (size_t index = 0; index < count; ++index) {
71 for (int pair = 0; pair < 2; ++pair) {
caryclarka35ab3e2016-10-20 08:32:18 -070072 const CubicPts& dPts = dCubic[index][pair];
73 SkDCubic d;
74 d.debugSet(dPts.fPts);
benjaminwagnerec4d4d72016-03-25 12:59:53 -070075 SkPoint c[4] = { {(float) d[0].fX, (float) d[0].fY}, {(float) d[1].fX, (float) d[1].fY},
caryclarkfeff7d22014-10-09 05:36:03 -070076 {(float) d[2].fX, (float) d[2].fY}, {(float) d[3].fX, (float) d[3].fY} };
benjaminwagnerec4d4d72016-03-25 12:59:53 -070077 cubicTest(c);
78 if (FLAGS_timeout && timer.elapsedMs() > MS_TEST_DURATION) {
caryclarkfeff7d22014-10-09 05:36:03 -070079 return;
80 }
benjaminwagnerec4d4d72016-03-25 12:59:53 -070081 }
82 }
caryclarkfeff7d22014-10-09 05:36:03 -070083}
84
caryclarka35ab3e2016-10-20 08:32:18 -070085static void quadSetTest(const QuadPts* dQuad, size_t count) {
benjaminwagnerec4d4d72016-03-25 12:59:53 -070086 skiatest::Timer timer;
87 for (size_t index = 0; index < count; ++index) {
caryclarka35ab3e2016-10-20 08:32:18 -070088 const QuadPts& dPts = dQuad[index];
89 SkDQuad d;
90 d.debugSet(dPts.fPts);
benjaminwagnerec4d4d72016-03-25 12:59:53 -070091 SkPoint c[3] = { {(float) d[0].fX, (float) d[0].fY}, {(float) d[1].fX, (float) d[1].fY},
caryclarkfeff7d22014-10-09 05:36:03 -070092 {(float) d[2].fX, (float) d[2].fY} };
benjaminwagnerec4d4d72016-03-25 12:59:53 -070093 quadTest(c);
94 if (FLAGS_timeout && timer.elapsedMs() > MS_TEST_DURATION) {
caryclarkfeff7d22014-10-09 05:36:03 -070095 return;
96 }
benjaminwagnerec4d4d72016-03-25 12:59:53 -070097 }
caryclarkfeff7d22014-10-09 05:36:03 -070098}
99
caryclarka35ab3e2016-10-20 08:32:18 -0700100static void quadPairSetTest(const QuadPts dQuad[][2], size_t count) {
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700101 skiatest::Timer timer;
102 for (size_t index = 0; index < count; ++index) {
103 for (int pair = 0; pair < 2; ++pair) {
caryclarka35ab3e2016-10-20 08:32:18 -0700104 const QuadPts& dPts = dQuad[index][pair];
105 SkDQuad d;
106 d.debugSet(dPts.fPts);
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700107 SkPoint c[3] = { {(float) d[0].fX, (float) d[0].fY}, {(float) d[1].fX, (float) d[1].fY},
caryclarkfeff7d22014-10-09 05:36:03 -0700108 {(float) d[2].fX, (float) d[2].fY} };
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700109 quadTest(c);
110 if (FLAGS_timeout && timer.elapsedMs() > MS_TEST_DURATION) {
caryclarkfeff7d22014-10-09 05:36:03 -0700111 return;
112 }
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700113 }
114 }
caryclarkfeff7d22014-10-09 05:36:03 -0700115}
116
117DEF_TEST(QuadStrokerSet, reporter) {
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700118 quadSetTest(quadraticLines, quadraticLines_count);
119 quadSetTest(quadraticPoints, quadraticPoints_count);
120 quadSetTest(quadraticModEpsilonLines, quadraticModEpsilonLines_count);
121 quadPairSetTest(quadraticTests, quadraticTests_count);
caryclarkfeff7d22014-10-09 05:36:03 -0700122}
123
124DEF_TEST(CubicStrokerSet, reporter) {
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700125 cubicSetTest(pointDegenerates, pointDegenerates_count);
126 cubicSetTest(notPointDegenerates, notPointDegenerates_count);
127 cubicSetTest(lines, lines_count);
128 cubicSetTest(notLines, notLines_count);
129 cubicSetTest(modEpsilonLines, modEpsilonLines_count);
130 cubicSetTest(lessEpsilonLines, lessEpsilonLines_count);
131 cubicSetTest(negEpsilonLines, negEpsilonLines_count);
132 cubicPairSetTest(tests, tests_count);
caryclarkfeff7d22014-10-09 05:36:03 -0700133}
134
scroggof9d61012014-12-15 12:54:51 -0800135static SkScalar unbounded(SkRandom& r) {
caryclarkfeff7d22014-10-09 05:36:03 -0700136 uint32_t val = r.nextU();
137 return SkBits2Float(val);
138}
139
scroggof9d61012014-12-15 12:54:51 -0800140static SkScalar unboundedPos(SkRandom& r) {
caryclarkfeff7d22014-10-09 05:36:03 -0700141 uint32_t val = r.nextU() & 0x7fffffff;
142 return SkBits2Float(val);
143}
144
145DEF_TEST(QuadStrokerUnbounded, reporter) {
scroggof9d61012014-12-15 12:54:51 -0800146 SkRandom r;
caryclarkfeff7d22014-10-09 05:36:03 -0700147 SkPaint p;
148 p.setStyle(SkPaint::kStroke_Style);
149#if defined(SK_DEBUG) && QUAD_STROKE_APPROXIMATION
150 int best = 0;
151 sk_bzero(gMaxRecursion, sizeof(gMaxRecursion[0]) * 3);
152#endif
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700153 skiatest::Timer timer;
caryclarkfeff7d22014-10-09 05:36:03 -0700154 for (int i = 0; i < 1000000; ++i) {
155 SkPath path, fill;
156 path.moveTo(unbounded(r), unbounded(r));
157 path.quadTo(unbounded(r), unbounded(r), unbounded(r), unbounded(r));
158 p.setStrokeWidth(unboundedPos(r));
159 p.getFillPath(path, &fill);
160#if defined(SK_DEBUG) && QUAD_STROKE_APPROXIMATION
161 if (best < gMaxRecursion[2]) {
caryclark99d59152014-10-09 07:08:59 -0700162 if (FLAGS_veryVerbose) {
caryclarkfeff7d22014-10-09 05:36:03 -0700163 SkDebugf("\n%s quad=%d width=%1.9g\n", __FUNCTION__, gMaxRecursion[2],
164 p.getStrokeWidth());
165 path.dumpHex();
166 SkDebugf("fill:\n");
167 fill.dumpHex();
168 }
169 best = gMaxRecursion[2];
170 }
171#endif
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700172 if (FLAGS_timeout && timer.elapsedMs() > MS_TEST_DURATION) {
caryclarkfeff7d22014-10-09 05:36:03 -0700173 return;
174 }
175 }
176#if defined(SK_DEBUG) && QUAD_STROKE_APPROXIMATION
caryclark99d59152014-10-09 07:08:59 -0700177 if (FLAGS_veryVerbose) {
caryclarkfeff7d22014-10-09 05:36:03 -0700178 SkDebugf("\n%s max quad=%d\n", __FUNCTION__, best);
179 }
180#endif
181}
182
183DEF_TEST(CubicStrokerUnbounded, reporter) {
scroggof9d61012014-12-15 12:54:51 -0800184 SkRandom r;
caryclarkfeff7d22014-10-09 05:36:03 -0700185 SkPaint p;
186 p.setStyle(SkPaint::kStroke_Style);
187#if defined(SK_DEBUG) && QUAD_STROKE_APPROXIMATION
188 int bestTan = 0;
189 int bestCubic = 0;
190 sk_bzero(gMaxRecursion, sizeof(gMaxRecursion[0]) * 3);
191#endif
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700192 skiatest::Timer timer;
caryclarkfeff7d22014-10-09 05:36:03 -0700193 for (int i = 0; i < 1000000; ++i) {
194 SkPath path, fill;
195 path.moveTo(unbounded(r), unbounded(r));
196 path.cubicTo(unbounded(r), unbounded(r), unbounded(r), unbounded(r),
197 unbounded(r), unbounded(r));
198 p.setStrokeWidth(unboundedPos(r));
199 p.getFillPath(path, &fill);
200 #if defined(SK_DEBUG) && QUAD_STROKE_APPROXIMATION
201 if (bestTan < gMaxRecursion[0] || bestCubic < gMaxRecursion[1]) {
caryclark99d59152014-10-09 07:08:59 -0700202 if (FLAGS_veryVerbose) {
caryclarkfeff7d22014-10-09 05:36:03 -0700203 SkDebugf("\n%s tan=%d cubic=%d width=%1.9g\n", __FUNCTION__, gMaxRecursion[0],
204 gMaxRecursion[1], p.getStrokeWidth());
205 path.dumpHex();
206 SkDebugf("fill:\n");
207 fill.dumpHex();
208 }
209 bestTan = SkTMax(bestTan, gMaxRecursion[0]);
210 bestCubic = SkTMax(bestCubic, gMaxRecursion[1]);
211 }
212 #endif
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700213 if (FLAGS_timeout && timer.elapsedMs() > MS_TEST_DURATION) {
caryclarkfeff7d22014-10-09 05:36:03 -0700214 return;
215 }
216 }
217#if defined(SK_DEBUG) && QUAD_STROKE_APPROXIMATION
caryclark99d59152014-10-09 07:08:59 -0700218 if (FLAGS_veryVerbose) {
caryclarkfeff7d22014-10-09 05:36:03 -0700219 SkDebugf("\n%s max tan=%d cubic=%d\n", __FUNCTION__, bestTan, bestCubic);
220 }
221#endif
222}
223
224DEF_TEST(QuadStrokerConstrained, reporter) {
scroggof9d61012014-12-15 12:54:51 -0800225 SkRandom r;
caryclarkfeff7d22014-10-09 05:36:03 -0700226 SkPaint p;
227 p.setStyle(SkPaint::kStroke_Style);
228#if defined(SK_DEBUG) && QUAD_STROKE_APPROXIMATION
229 int best = 0;
230 sk_bzero(gMaxRecursion, sizeof(gMaxRecursion[0]) * 3);
231#endif
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700232 skiatest::Timer timer;
caryclarkfeff7d22014-10-09 05:36:03 -0700233 for (int i = 0; i < 1000000; ++i) {
234 SkPath path, fill;
235 SkPoint quad[3];
236 quad[0].fX = r.nextRangeF(0, 500);
237 quad[0].fY = r.nextRangeF(0, 500);
238 const SkScalar halfSquared = 0.5f * 0.5f;
239 do {
240 quad[1].fX = r.nextRangeF(0, 500);
241 quad[1].fY = r.nextRangeF(0, 500);
242 } while (quad[0].distanceToSqd(quad[1]) < halfSquared);
243 do {
244 quad[2].fX = r.nextRangeF(0, 500);
245 quad[2].fY = r.nextRangeF(0, 500);
246 } while (quad[0].distanceToSqd(quad[2]) < halfSquared
247 || quad[1].distanceToSqd(quad[2]) < halfSquared);
248 path.moveTo(quad[0].fX, quad[0].fY);
249 path.quadTo(quad[1].fX, quad[1].fY, quad[2].fX, quad[2].fY);
250 p.setStrokeWidth(r.nextRangeF(0, 500));
251 p.getFillPath(path, &fill);
252#if defined(SK_DEBUG) && QUAD_STROKE_APPROXIMATION
253 if (best < gMaxRecursion[2]) {
caryclark99d59152014-10-09 07:08:59 -0700254 if (FLAGS_veryVerbose) {
caryclarkfeff7d22014-10-09 05:36:03 -0700255 SkDebugf("\n%s quad=%d width=%1.9g\n", __FUNCTION__, gMaxRecursion[2],
256 p.getStrokeWidth());
257 path.dumpHex();
258 SkDebugf("fill:\n");
259 fill.dumpHex();
260 }
261 best = gMaxRecursion[2];
262 }
263#endif
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700264 if (FLAGS_timeout && timer.elapsedMs() > MS_TEST_DURATION) {
caryclarkfeff7d22014-10-09 05:36:03 -0700265 return;
266 }
267 }
268#if defined(SK_DEBUG) && QUAD_STROKE_APPROXIMATION
caryclark99d59152014-10-09 07:08:59 -0700269 if (FLAGS_veryVerbose) {
caryclarkfeff7d22014-10-09 05:36:03 -0700270 SkDebugf("\n%s max quad=%d\n", __FUNCTION__, best);
271 }
272#endif
273}
274
275DEF_TEST(CubicStrokerConstrained, reporter) {
scroggof9d61012014-12-15 12:54:51 -0800276 SkRandom r;
caryclarkfeff7d22014-10-09 05:36:03 -0700277 SkPaint p;
278 p.setStyle(SkPaint::kStroke_Style);
279#if defined(SK_DEBUG) && QUAD_STROKE_APPROXIMATION
280 int bestTan = 0;
281 int bestCubic = 0;
282 sk_bzero(gMaxRecursion, sizeof(gMaxRecursion[0]) * 3);
283#endif
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700284 skiatest::Timer timer;
caryclarkfeff7d22014-10-09 05:36:03 -0700285 for (int i = 0; i < 1000000; ++i) {
286 SkPath path, fill;
287 SkPoint cubic[4];
288 cubic[0].fX = r.nextRangeF(0, 500);
289 cubic[0].fY = r.nextRangeF(0, 500);
290 const SkScalar halfSquared = 0.5f * 0.5f;
291 do {
292 cubic[1].fX = r.nextRangeF(0, 500);
293 cubic[1].fY = r.nextRangeF(0, 500);
294 } while (cubic[0].distanceToSqd(cubic[1]) < halfSquared);
295 do {
296 cubic[2].fX = r.nextRangeF(0, 500);
297 cubic[2].fY = r.nextRangeF(0, 500);
298 } while ( cubic[0].distanceToSqd(cubic[2]) < halfSquared
299 || cubic[1].distanceToSqd(cubic[2]) < halfSquared);
300 do {
301 cubic[3].fX = r.nextRangeF(0, 500);
302 cubic[3].fY = r.nextRangeF(0, 500);
303 } while ( cubic[0].distanceToSqd(cubic[3]) < halfSquared
304 || cubic[1].distanceToSqd(cubic[3]) < halfSquared
305 || cubic[2].distanceToSqd(cubic[3]) < halfSquared);
306 path.moveTo(cubic[0].fX, cubic[0].fY);
307 path.cubicTo(cubic[1].fX, cubic[1].fY, cubic[2].fX, cubic[2].fY, cubic[3].fX, cubic[3].fY);
308 p.setStrokeWidth(r.nextRangeF(0, 500));
309 p.getFillPath(path, &fill);
310#if defined(SK_DEBUG) && QUAD_STROKE_APPROXIMATION
311 if (bestTan < gMaxRecursion[0] || bestCubic < gMaxRecursion[1]) {
caryclark99d59152014-10-09 07:08:59 -0700312 if (FLAGS_veryVerbose) {
caryclarkfeff7d22014-10-09 05:36:03 -0700313 SkDebugf("\n%s tan=%d cubic=%d width=%1.9g\n", __FUNCTION__, gMaxRecursion[0],
314 gMaxRecursion[1], p.getStrokeWidth());
315 path.dumpHex();
316 SkDebugf("fill:\n");
317 fill.dumpHex();
318 }
319 bestTan = SkTMax(bestTan, gMaxRecursion[0]);
320 bestCubic = SkTMax(bestCubic, gMaxRecursion[1]);
321 }
322#endif
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700323 if (FLAGS_timeout && timer.elapsedMs() > MS_TEST_DURATION) {
caryclarkfeff7d22014-10-09 05:36:03 -0700324 return;
325 }
326 }
327#if defined(SK_DEBUG) && QUAD_STROKE_APPROXIMATION
caryclark99d59152014-10-09 07:08:59 -0700328 if (FLAGS_veryVerbose) {
caryclarkfeff7d22014-10-09 05:36:03 -0700329 SkDebugf("\n%s max tan=%d cubic=%d\n", __FUNCTION__, bestTan, bestCubic);
330 }
331#endif
332}
333
334DEF_TEST(QuadStrokerRange, reporter) {
scroggof9d61012014-12-15 12:54:51 -0800335 SkRandom r;
caryclarkfeff7d22014-10-09 05:36:03 -0700336 SkPaint p;
337 p.setStyle(SkPaint::kStroke_Style);
338#if defined(SK_DEBUG) && QUAD_STROKE_APPROXIMATION
339 int best = 0;
340 sk_bzero(gMaxRecursion, sizeof(gMaxRecursion[0]) * 3);
341#endif
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700342 skiatest::Timer timer;
caryclarkfeff7d22014-10-09 05:36:03 -0700343 for (int i = 0; i < 1000000; ++i) {
344 SkPath path, fill;
345 SkPoint quad[3];
346 quad[0].fX = r.nextRangeF(0, 500);
347 quad[0].fY = r.nextRangeF(0, 500);
348 quad[1].fX = r.nextRangeF(0, 500);
349 quad[1].fY = r.nextRangeF(0, 500);
350 quad[2].fX = r.nextRangeF(0, 500);
351 quad[2].fY = r.nextRangeF(0, 500);
352 path.moveTo(quad[0].fX, quad[0].fY);
353 path.quadTo(quad[1].fX, quad[1].fY, quad[2].fX, quad[2].fY);
354 p.setStrokeWidth(r.nextRangeF(0, 500));
355 p.getFillPath(path, &fill);
356#if defined(SK_DEBUG) && QUAD_STROKE_APPROXIMATION
357 if (best < gMaxRecursion[2]) {
caryclark99d59152014-10-09 07:08:59 -0700358 if (FLAGS_veryVerbose) {
caryclarkfeff7d22014-10-09 05:36:03 -0700359 SkDebugf("\n%s quad=%d width=%1.9g\n", __FUNCTION__, gMaxRecursion[2],
360 p.getStrokeWidth());
361 path.dumpHex();
362 SkDebugf("fill:\n");
363 fill.dumpHex();
364 }
365 best = gMaxRecursion[2];
366 }
367#endif
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700368 if (FLAGS_timeout && timer.elapsedMs() > MS_TEST_DURATION) {
caryclarkfeff7d22014-10-09 05:36:03 -0700369 return;
370 }
371 }
372#if defined(SK_DEBUG) && QUAD_STROKE_APPROXIMATION
373 if (FLAGS_verbose) {
374 SkDebugf("\n%s max quad=%d\n", __FUNCTION__, best);
375 }
376#endif
377}
378
379DEF_TEST(CubicStrokerRange, reporter) {
scroggof9d61012014-12-15 12:54:51 -0800380 SkRandom r;
caryclarkfeff7d22014-10-09 05:36:03 -0700381 SkPaint p;
382 p.setStyle(SkPaint::kStroke_Style);
383#if defined(SK_DEBUG) && QUAD_STROKE_APPROXIMATION
384 int best[2] = { 0 };
385 sk_bzero(gMaxRecursion, sizeof(gMaxRecursion[0]) * 3);
386#endif
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700387 skiatest::Timer timer;
caryclarkfeff7d22014-10-09 05:36:03 -0700388 for (int i = 0; i < 1000000; ++i) {
389 SkPath path, fill;
390 path.moveTo(r.nextRangeF(0, 500), r.nextRangeF(0, 500));
391 path.cubicTo(r.nextRangeF(0, 500), r.nextRangeF(0, 500), r.nextRangeF(0, 500),
392 r.nextRangeF(0, 500), r.nextRangeF(0, 500), r.nextRangeF(0, 500));
393 p.setStrokeWidth(r.nextRangeF(0, 100));
394 p.getFillPath(path, &fill);
395#if defined(SK_DEBUG) && QUAD_STROKE_APPROXIMATION
396 if (best[0] < gMaxRecursion[0] || best[1] < gMaxRecursion[1]) {
caryclark99d59152014-10-09 07:08:59 -0700397 if (FLAGS_veryVerbose) {
caryclarkfeff7d22014-10-09 05:36:03 -0700398 SkDebugf("\n%s tan=%d cubic=%d width=%1.9g\n", __FUNCTION__, gMaxRecursion[0],
399 gMaxRecursion[1], p.getStrokeWidth());
400 path.dumpHex();
401 SkDebugf("fill:\n");
402 fill.dumpHex();
403 }
404 best[0] = SkTMax(best[0], gMaxRecursion[0]);
405 best[1] = SkTMax(best[1], gMaxRecursion[1]);
406 }
407#endif
benjaminwagnerec4d4d72016-03-25 12:59:53 -0700408 if (FLAGS_timeout && timer.elapsedMs() > MS_TEST_DURATION) {
caryclarkfeff7d22014-10-09 05:36:03 -0700409 return;
410 }
411 }
412#if defined(SK_DEBUG) && QUAD_STROKE_APPROXIMATION
caryclark99d59152014-10-09 07:08:59 -0700413 if (FLAGS_veryVerbose) {
caryclarkfeff7d22014-10-09 05:36:03 -0700414 SkDebugf("\n%s max tan=%d cubic=%d\n", __FUNCTION__, best[0], best[1]);
415 }
416#endif
417}
418
419
420DEF_TEST(QuadStrokerOneOff, reporter) {
421#if defined(SK_DEBUG) && QUAD_STROKE_APPROXIMATION
422 sk_bzero(gMaxRecursion, sizeof(gMaxRecursion[0]) * 3);
423#endif
424 SkPaint p;
425 p.setStyle(SkPaint::kStroke_Style);
426 p.setStrokeWidth(SkDoubleToScalar(164.683548));
427
428 SkPath path, fill;
429path.moveTo(SkBits2Float(0x43c99223), SkBits2Float(0x42b7417e));
430path.quadTo(SkBits2Float(0x4285d839), SkBits2Float(0x43ed6645), SkBits2Float(0x43c941c8), SkBits2Float(0x42b3ace3));
431 p.getFillPath(path, &fill);
caryclark99d59152014-10-09 07:08:59 -0700432 if (FLAGS_veryVerbose) {
caryclarkfeff7d22014-10-09 05:36:03 -0700433 SkDebugf("\n%s path\n", __FUNCTION__);
434 path.dump();
435 SkDebugf("fill:\n");
436 fill.dump();
437 }
438#if defined(SK_DEBUG) && QUAD_STROKE_APPROXIMATION
caryclark99d59152014-10-09 07:08:59 -0700439 if (FLAGS_veryVerbose) {
caryclarkfeff7d22014-10-09 05:36:03 -0700440 SkDebugf("max quad=%d\n", gMaxRecursion[2]);
441 }
442#endif
443}
444
445DEF_TEST(CubicStrokerOneOff, reporter) {
446#if defined(SK_DEBUG) && QUAD_STROKE_APPROXIMATION
447 sk_bzero(gMaxRecursion, sizeof(gMaxRecursion[0]) * 3);
448#endif
449 SkPaint p;
450 p.setStyle(SkPaint::kStroke_Style);
451 p.setStrokeWidth(SkDoubleToScalar(42.835968));
452
453 SkPath path, fill;
454path.moveTo(SkBits2Float(0x433f5370), SkBits2Float(0x43d1f4b3));
455path.cubicTo(SkBits2Float(0x4331cb76), SkBits2Float(0x43ea3340), SkBits2Float(0x4388f498), SkBits2Float(0x42f7f08d), SkBits2Float(0x43f1cd32), SkBits2Float(0x42802ec1));
456 p.getFillPath(path, &fill);
caryclark99d59152014-10-09 07:08:59 -0700457 if (FLAGS_veryVerbose) {
caryclarkfeff7d22014-10-09 05:36:03 -0700458 SkDebugf("\n%s path\n", __FUNCTION__);
459 path.dump();
460 SkDebugf("fill:\n");
461 fill.dump();
462 }
463#if defined(SK_DEBUG) && QUAD_STROKE_APPROXIMATION
caryclark99d59152014-10-09 07:08:59 -0700464 if (FLAGS_veryVerbose) {
caryclarkfeff7d22014-10-09 05:36:03 -0700465 SkDebugf("max tan=%d cubic=%d\n", gMaxRecursion[0], gMaxRecursion[1]);
466 }
467#endif
468}