1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2013 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkDebug.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTemplates.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkArenaAlloc.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkFloatBits.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkRandom.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkIntersections.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkOpAngle.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkOpContour.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkOpSegment.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsLine.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsPoint.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsQuad.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsTypes.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "tests/PathOpsTestCommon.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
25*c8dee2aaSAndroid Build Coastguard Worker
26*c8dee2aaSAndroid Build Coastguard Worker #include <array>
27*c8dee2aaSAndroid Build Coastguard Worker #include <cfloat>
28*c8dee2aaSAndroid Build Coastguard Worker #include <cmath>
29*c8dee2aaSAndroid Build Coastguard Worker
30*c8dee2aaSAndroid Build Coastguard Worker static bool gDisableAngleTests = true;
31*c8dee2aaSAndroid Build Coastguard Worker
next(float f)32*c8dee2aaSAndroid Build Coastguard Worker static float next(float f)
33*c8dee2aaSAndroid Build Coastguard Worker {
34*c8dee2aaSAndroid Build Coastguard Worker int fBits = SkFloatAs2sCompliment(f);
35*c8dee2aaSAndroid Build Coastguard Worker ++fBits;
36*c8dee2aaSAndroid Build Coastguard Worker float fNext = Sk2sComplimentAsFloat(fBits);
37*c8dee2aaSAndroid Build Coastguard Worker return fNext;
38*c8dee2aaSAndroid Build Coastguard Worker }
39*c8dee2aaSAndroid Build Coastguard Worker
prev(float f)40*c8dee2aaSAndroid Build Coastguard Worker static float prev(float f)
41*c8dee2aaSAndroid Build Coastguard Worker {
42*c8dee2aaSAndroid Build Coastguard Worker int fBits = SkFloatAs2sCompliment(f);
43*c8dee2aaSAndroid Build Coastguard Worker --fBits;
44*c8dee2aaSAndroid Build Coastguard Worker float fNext = Sk2sComplimentAsFloat(fBits);
45*c8dee2aaSAndroid Build Coastguard Worker return fNext;
46*c8dee2aaSAndroid Build Coastguard Worker }
47*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(PathOpsAngleFindCrossEpsilon,reporter)48*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(PathOpsAngleFindCrossEpsilon, reporter) {
49*c8dee2aaSAndroid Build Coastguard Worker if (gDisableAngleTests) {
50*c8dee2aaSAndroid Build Coastguard Worker return;
51*c8dee2aaSAndroid Build Coastguard Worker }
52*c8dee2aaSAndroid Build Coastguard Worker SkRandom ran;
53*c8dee2aaSAndroid Build Coastguard Worker int maxEpsilon = 0;
54*c8dee2aaSAndroid Build Coastguard Worker for (int index = 0; index < 10000000; ++index) {
55*c8dee2aaSAndroid Build Coastguard Worker SkDLine line = {{{0, 0}, {ran.nextRangeF(0.0001f, 1000), ran.nextRangeF(0.0001f, 1000)}}};
56*c8dee2aaSAndroid Build Coastguard Worker for (int inner = 0; inner < 10; ++inner) {
57*c8dee2aaSAndroid Build Coastguard Worker float t = ran.nextRangeF(0.0001f, 1);
58*c8dee2aaSAndroid Build Coastguard Worker SkDPoint dPt = line.ptAtT(t);
59*c8dee2aaSAndroid Build Coastguard Worker SkPoint pt = dPt.asSkPoint();
60*c8dee2aaSAndroid Build Coastguard Worker float xs[3] = { prev(pt.fX), pt.fX, next(pt.fX) };
61*c8dee2aaSAndroid Build Coastguard Worker float ys[3] = { prev(pt.fY), pt.fY, next(pt.fY) };
62*c8dee2aaSAndroid Build Coastguard Worker for (int xIdx = 0; xIdx < 3; ++xIdx) {
63*c8dee2aaSAndroid Build Coastguard Worker for (int yIdx = 0; yIdx < 3; ++yIdx) {
64*c8dee2aaSAndroid Build Coastguard Worker SkPoint test = { xs[xIdx], ys[yIdx] };
65*c8dee2aaSAndroid Build Coastguard Worker float p1 = SkDoubleToScalar(line[1].fX * test.fY);
66*c8dee2aaSAndroid Build Coastguard Worker float p2 = SkDoubleToScalar(line[1].fY * test.fX);
67*c8dee2aaSAndroid Build Coastguard Worker int p1Bits = SkFloatAs2sCompliment(p1);
68*c8dee2aaSAndroid Build Coastguard Worker int p2Bits = SkFloatAs2sCompliment(p2);
69*c8dee2aaSAndroid Build Coastguard Worker int epsilon = SkTAbs(p1Bits - p2Bits);
70*c8dee2aaSAndroid Build Coastguard Worker if (maxEpsilon < epsilon) {
71*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("line={{0, 0}, {%1.7g, %1.7g}} t=%1.7g pt={%1.7g, %1.7g}"
72*c8dee2aaSAndroid Build Coastguard Worker " epsilon=%d\n",
73*c8dee2aaSAndroid Build Coastguard Worker line[1].fX, line[1].fY, t, test.fX, test.fY, epsilon);
74*c8dee2aaSAndroid Build Coastguard Worker maxEpsilon = epsilon;
75*c8dee2aaSAndroid Build Coastguard Worker }
76*c8dee2aaSAndroid Build Coastguard Worker }
77*c8dee2aaSAndroid Build Coastguard Worker }
78*c8dee2aaSAndroid Build Coastguard Worker }
79*c8dee2aaSAndroid Build Coastguard Worker }
80*c8dee2aaSAndroid Build Coastguard Worker }
81*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(PathOpsAngleFindQuadEpsilon,reporter)82*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(PathOpsAngleFindQuadEpsilon, reporter) {
83*c8dee2aaSAndroid Build Coastguard Worker if (gDisableAngleTests) {
84*c8dee2aaSAndroid Build Coastguard Worker return;
85*c8dee2aaSAndroid Build Coastguard Worker }
86*c8dee2aaSAndroid Build Coastguard Worker SkRandom ran;
87*c8dee2aaSAndroid Build Coastguard Worker int maxEpsilon = 0;
88*c8dee2aaSAndroid Build Coastguard Worker double maxAngle = 0;
89*c8dee2aaSAndroid Build Coastguard Worker for (int index = 0; index < 100000; ++index) {
90*c8dee2aaSAndroid Build Coastguard Worker SkDLine line = {{{0, 0}, {ran.nextRangeF(0.0001f, 1000), ran.nextRangeF(0.0001f, 1000)}}};
91*c8dee2aaSAndroid Build Coastguard Worker float t = ran.nextRangeF(0.0001f, 1);
92*c8dee2aaSAndroid Build Coastguard Worker SkDPoint dPt = line.ptAtT(t);
93*c8dee2aaSAndroid Build Coastguard Worker float t2 = ran.nextRangeF(0.0001f, 1);
94*c8dee2aaSAndroid Build Coastguard Worker SkDPoint qPt = line.ptAtT(t2);
95*c8dee2aaSAndroid Build Coastguard Worker float t3 = ran.nextRangeF(0.0001f, 1);
96*c8dee2aaSAndroid Build Coastguard Worker SkDPoint qPt2 = line.ptAtT(t3);
97*c8dee2aaSAndroid Build Coastguard Worker qPt.fX += qPt2.fY;
98*c8dee2aaSAndroid Build Coastguard Worker qPt.fY -= qPt2.fX;
99*c8dee2aaSAndroid Build Coastguard Worker QuadPts q = {{line[0], dPt, qPt}};
100*c8dee2aaSAndroid Build Coastguard Worker SkDQuad quad;
101*c8dee2aaSAndroid Build Coastguard Worker quad.debugSet(q.fPts);
102*c8dee2aaSAndroid Build Coastguard Worker // binary search for maximum movement of quad[1] towards test that still has 1 intersection
103*c8dee2aaSAndroid Build Coastguard Worker double moveT = 0.5f;
104*c8dee2aaSAndroid Build Coastguard Worker double deltaT = moveT / 2;
105*c8dee2aaSAndroid Build Coastguard Worker SkDPoint last;
106*c8dee2aaSAndroid Build Coastguard Worker do {
107*c8dee2aaSAndroid Build Coastguard Worker last = quad[1];
108*c8dee2aaSAndroid Build Coastguard Worker quad[1].fX = dPt.fX - line[1].fY * moveT;
109*c8dee2aaSAndroid Build Coastguard Worker quad[1].fY = dPt.fY + line[1].fX * moveT;
110*c8dee2aaSAndroid Build Coastguard Worker SkIntersections i;
111*c8dee2aaSAndroid Build Coastguard Worker i.intersect(quad, line);
112*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, i.used() > 0);
113*c8dee2aaSAndroid Build Coastguard Worker if (i.used() == 1) {
114*c8dee2aaSAndroid Build Coastguard Worker moveT += deltaT;
115*c8dee2aaSAndroid Build Coastguard Worker } else {
116*c8dee2aaSAndroid Build Coastguard Worker moveT -= deltaT;
117*c8dee2aaSAndroid Build Coastguard Worker }
118*c8dee2aaSAndroid Build Coastguard Worker deltaT /= 2;
119*c8dee2aaSAndroid Build Coastguard Worker } while (last.asSkPoint() != quad[1].asSkPoint());
120*c8dee2aaSAndroid Build Coastguard Worker float p1 = SkDoubleToScalar(line[1].fX * last.fY);
121*c8dee2aaSAndroid Build Coastguard Worker float p2 = SkDoubleToScalar(line[1].fY * last.fX);
122*c8dee2aaSAndroid Build Coastguard Worker int p1Bits = SkFloatAs2sCompliment(p1);
123*c8dee2aaSAndroid Build Coastguard Worker int p2Bits = SkFloatAs2sCompliment(p2);
124*c8dee2aaSAndroid Build Coastguard Worker int epsilon = SkTAbs(p1Bits - p2Bits);
125*c8dee2aaSAndroid Build Coastguard Worker if (maxEpsilon < epsilon) {
126*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("line={{0, 0}, {%1.7g, %1.7g}} t=%1.7g/%1.7g/%1.7g moveT=%1.7g"
127*c8dee2aaSAndroid Build Coastguard Worker " pt={%1.7g, %1.7g} epsilon=%d\n",
128*c8dee2aaSAndroid Build Coastguard Worker line[1].fX, line[1].fY, t, t2, t3, moveT, last.fX, last.fY, epsilon);
129*c8dee2aaSAndroid Build Coastguard Worker maxEpsilon = epsilon;
130*c8dee2aaSAndroid Build Coastguard Worker }
131*c8dee2aaSAndroid Build Coastguard Worker double a1 = atan2(line[1].fY, line[1].fX);
132*c8dee2aaSAndroid Build Coastguard Worker double a2 = atan2(last.fY, last.fX);
133*c8dee2aaSAndroid Build Coastguard Worker double angle = fabs(a1 - a2);
134*c8dee2aaSAndroid Build Coastguard Worker if (maxAngle < angle) {
135*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("line={{0, 0}, {%1.7g, %1.7g}} t=%1.7g/%1.7g/%1.7g moveT=%1.7g"
136*c8dee2aaSAndroid Build Coastguard Worker " pt={%1.7g, %1.7g} angle=%1.7g\n",
137*c8dee2aaSAndroid Build Coastguard Worker line[1].fX, line[1].fY, t, t2, t3, moveT, last.fX, last.fY, angle);
138*c8dee2aaSAndroid Build Coastguard Worker maxAngle = angle;
139*c8dee2aaSAndroid Build Coastguard Worker }
140*c8dee2aaSAndroid Build Coastguard Worker }
141*c8dee2aaSAndroid Build Coastguard Worker }
142*c8dee2aaSAndroid Build Coastguard Worker
find_slop(double x,double y,double rx,double ry)143*c8dee2aaSAndroid Build Coastguard Worker static int find_slop(double x, double y, double rx, double ry) {
144*c8dee2aaSAndroid Build Coastguard Worker int slopBits = 0;
145*c8dee2aaSAndroid Build Coastguard Worker bool less1, less2;
146*c8dee2aaSAndroid Build Coastguard Worker double absX = fabs(x);
147*c8dee2aaSAndroid Build Coastguard Worker double absY = fabs(y);
148*c8dee2aaSAndroid Build Coastguard Worker double length = absX < absY ? absX / 2 + absY : absX + absY / 2;
149*c8dee2aaSAndroid Build Coastguard Worker int exponent;
150*c8dee2aaSAndroid Build Coastguard Worker (void) frexp(length, &exponent);
151*c8dee2aaSAndroid Build Coastguard Worker double epsilon = ldexp(FLT_EPSILON, exponent);
152*c8dee2aaSAndroid Build Coastguard Worker do {
153*c8dee2aaSAndroid Build Coastguard Worker // get the length as the larger plus half the smaller (both same signs)
154*c8dee2aaSAndroid Build Coastguard Worker // find the ulps of the length
155*c8dee2aaSAndroid Build Coastguard Worker // compute the offsets from there
156*c8dee2aaSAndroid Build Coastguard Worker double xSlop = epsilon * slopBits;
157*c8dee2aaSAndroid Build Coastguard Worker double ySlop = x * y < 0 ? -xSlop : xSlop; // OPTIMIZATION: use copysign / _copysign ?
158*c8dee2aaSAndroid Build Coastguard Worker double x1 = x - xSlop;
159*c8dee2aaSAndroid Build Coastguard Worker double y1 = y + ySlop;
160*c8dee2aaSAndroid Build Coastguard Worker double x_ry1 = x1 * ry;
161*c8dee2aaSAndroid Build Coastguard Worker double rx_y1 = rx * y1;
162*c8dee2aaSAndroid Build Coastguard Worker less1 = x_ry1 < rx_y1;
163*c8dee2aaSAndroid Build Coastguard Worker double x2 = x + xSlop;
164*c8dee2aaSAndroid Build Coastguard Worker double y2 = y - ySlop;
165*c8dee2aaSAndroid Build Coastguard Worker double x_ry2 = x2 * ry;
166*c8dee2aaSAndroid Build Coastguard Worker double rx_y2 = rx * y2;
167*c8dee2aaSAndroid Build Coastguard Worker less2 = x_ry2 < rx_y2;
168*c8dee2aaSAndroid Build Coastguard Worker } while (less1 == less2 && ++slopBits);
169*c8dee2aaSAndroid Build Coastguard Worker return slopBits;
170*c8dee2aaSAndroid Build Coastguard Worker }
171*c8dee2aaSAndroid Build Coastguard Worker
172*c8dee2aaSAndroid Build Coastguard Worker // from http://stackoverflow.com/questions/1427422/cheap-algorithm-to-find-measure-of-angle-between-vectors
diamond_angle(double y,double x)173*c8dee2aaSAndroid Build Coastguard Worker static double diamond_angle(double y, double x)
174*c8dee2aaSAndroid Build Coastguard Worker {
175*c8dee2aaSAndroid Build Coastguard Worker if (y >= 0)
176*c8dee2aaSAndroid Build Coastguard Worker return (x >= 0 ? y/(x+y) : 1-x/(-x+y));
177*c8dee2aaSAndroid Build Coastguard Worker else
178*c8dee2aaSAndroid Build Coastguard Worker return (x < 0 ? 2-y/(-x-y) : 3+x/(x-y));
179*c8dee2aaSAndroid Build Coastguard Worker }
180*c8dee2aaSAndroid Build Coastguard Worker
181*c8dee2aaSAndroid Build Coastguard Worker static const double slopTests[][4] = {
182*c8dee2aaSAndroid Build Coastguard Worker // x y rx ry
183*c8dee2aaSAndroid Build Coastguard Worker {-0.058554756452593892, -0.18804585843827226, -0.018568569646021160, -0.059615294434479438},
184*c8dee2aaSAndroid Build Coastguard Worker {-0.0013717412948608398, 0.0041152238845825195, -0.00045837944195925573, 0.0013753175735478074},
185*c8dee2aaSAndroid Build Coastguard Worker {-2.1033774145221198, -1.4046019261273715e-008, -0.70062688352066704, -1.2706324683777995e-008},
186*c8dee2aaSAndroid Build Coastguard Worker };
187*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(PathOpsAngleFindSlop,reporter)188*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(PathOpsAngleFindSlop, reporter) {
189*c8dee2aaSAndroid Build Coastguard Worker if (gDisableAngleTests) {
190*c8dee2aaSAndroid Build Coastguard Worker return;
191*c8dee2aaSAndroid Build Coastguard Worker }
192*c8dee2aaSAndroid Build Coastguard Worker for (int index = 0; index < (int) std::size(slopTests); ++index) {
193*c8dee2aaSAndroid Build Coastguard Worker const double* slopTest = slopTests[index];
194*c8dee2aaSAndroid Build Coastguard Worker double x = slopTest[0];
195*c8dee2aaSAndroid Build Coastguard Worker double y = slopTest[1];
196*c8dee2aaSAndroid Build Coastguard Worker double rx = slopTest[2];
197*c8dee2aaSAndroid Build Coastguard Worker double ry = slopTest[3];
198*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("%s xy %d=%d\n", __FUNCTION__, index, find_slop(x, y, rx, ry));
199*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("%s rxy %d=%d\n", __FUNCTION__, index, find_slop(rx, ry, x, y));
200*c8dee2aaSAndroid Build Coastguard Worker double angle = diamond_angle(y, x);
201*c8dee2aaSAndroid Build Coastguard Worker double rAngle = diamond_angle(ry, rx);
202*c8dee2aaSAndroid Build Coastguard Worker double diff = fabs(angle - rAngle);
203*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("%s diamond xy=%1.9g rxy=%1.9g diff=%1.9g factor=%d\n", __FUNCTION__,
204*c8dee2aaSAndroid Build Coastguard Worker angle, rAngle, diff, (int) (diff / FLT_EPSILON));
205*c8dee2aaSAndroid Build Coastguard Worker }
206*c8dee2aaSAndroid Build Coastguard Worker }
207*c8dee2aaSAndroid Build Coastguard Worker
208*c8dee2aaSAndroid Build Coastguard Worker class PathOpsAngleTester {
209*c8dee2aaSAndroid Build Coastguard Worker public:
After(SkOpAngle & lh,SkOpAngle & rh)210*c8dee2aaSAndroid Build Coastguard Worker static int After(SkOpAngle& lh, SkOpAngle& rh) {
211*c8dee2aaSAndroid Build Coastguard Worker return lh.after(&rh);
212*c8dee2aaSAndroid Build Coastguard Worker }
213*c8dee2aaSAndroid Build Coastguard Worker
AllOnOneSide(SkOpAngle & lh,SkOpAngle & rh)214*c8dee2aaSAndroid Build Coastguard Worker static int AllOnOneSide(SkOpAngle& lh, SkOpAngle& rh) {
215*c8dee2aaSAndroid Build Coastguard Worker return lh.lineOnOneSide(&rh, false);
216*c8dee2aaSAndroid Build Coastguard Worker }
217*c8dee2aaSAndroid Build Coastguard Worker
ConvexHullOverlaps(SkOpAngle & lh,SkOpAngle & rh)218*c8dee2aaSAndroid Build Coastguard Worker static int ConvexHullOverlaps(SkOpAngle& lh, SkOpAngle& rh) {
219*c8dee2aaSAndroid Build Coastguard Worker return lh.convexHullOverlaps(&rh);
220*c8dee2aaSAndroid Build Coastguard Worker }
221*c8dee2aaSAndroid Build Coastguard Worker
Orderable(SkOpAngle & lh,SkOpAngle & rh)222*c8dee2aaSAndroid Build Coastguard Worker static int Orderable(SkOpAngle& lh, SkOpAngle& rh) {
223*c8dee2aaSAndroid Build Coastguard Worker return lh.orderable(&rh);
224*c8dee2aaSAndroid Build Coastguard Worker }
225*c8dee2aaSAndroid Build Coastguard Worker
EndsIntersect(SkOpAngle & lh,SkOpAngle & rh)226*c8dee2aaSAndroid Build Coastguard Worker static int EndsIntersect(SkOpAngle& lh, SkOpAngle& rh) {
227*c8dee2aaSAndroid Build Coastguard Worker return lh.endsIntersect(&rh);
228*c8dee2aaSAndroid Build Coastguard Worker }
229*c8dee2aaSAndroid Build Coastguard Worker
SetNext(SkOpAngle & lh,SkOpAngle & rh)230*c8dee2aaSAndroid Build Coastguard Worker static void SetNext(SkOpAngle& lh, SkOpAngle& rh) {
231*c8dee2aaSAndroid Build Coastguard Worker lh.fNext = &rh;
232*c8dee2aaSAndroid Build Coastguard Worker }
233*c8dee2aaSAndroid Build Coastguard Worker };
234*c8dee2aaSAndroid Build Coastguard Worker
235*c8dee2aaSAndroid Build Coastguard Worker class PathOpsSegmentTester {
236*c8dee2aaSAndroid Build Coastguard Worker public:
DebugReset(SkOpSegment * segment)237*c8dee2aaSAndroid Build Coastguard Worker static void DebugReset(SkOpSegment* segment) {
238*c8dee2aaSAndroid Build Coastguard Worker segment->debugReset();
239*c8dee2aaSAndroid Build Coastguard Worker }
240*c8dee2aaSAndroid Build Coastguard Worker };
241*c8dee2aaSAndroid Build Coastguard Worker
242*c8dee2aaSAndroid Build Coastguard Worker struct CircleData {
243*c8dee2aaSAndroid Build Coastguard Worker const CubicPts fPts;
244*c8dee2aaSAndroid Build Coastguard Worker const int fPtCount;
245*c8dee2aaSAndroid Build Coastguard Worker SkPoint fShortPts[4];
246*c8dee2aaSAndroid Build Coastguard Worker };
247*c8dee2aaSAndroid Build Coastguard Worker
248*c8dee2aaSAndroid Build Coastguard Worker static CircleData circleDataSet[] = {
249*c8dee2aaSAndroid Build Coastguard Worker { {{{313.0155029296875, 207.90290832519531}, {320.05078125, 227.58743286132812}}}, 2, {} },
250*c8dee2aaSAndroid Build Coastguard Worker { {{{313.0155029296875, 207.90290832519531}, {313.98246891063195, 219.33615203830394},
251*c8dee2aaSAndroid Build Coastguard Worker {320.05078125, 227.58743286132812}}}, 3, {} },
252*c8dee2aaSAndroid Build Coastguard Worker };
253*c8dee2aaSAndroid Build Coastguard Worker
254*c8dee2aaSAndroid Build Coastguard Worker static const int circleDataSetSize = (int) std::size(circleDataSet);
255*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(PathOpsAngleCircle,reporter)256*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(PathOpsAngleCircle, reporter) {
257*c8dee2aaSAndroid Build Coastguard Worker SkSTArenaAlloc<4096> allocator;
258*c8dee2aaSAndroid Build Coastguard Worker SkOpContourHead contour;
259*c8dee2aaSAndroid Build Coastguard Worker SkOpGlobalState state(&contour, &allocator SkDEBUGPARAMS(false) SkDEBUGPARAMS(nullptr));
260*c8dee2aaSAndroid Build Coastguard Worker contour.init(&state, false, false);
261*c8dee2aaSAndroid Build Coastguard Worker for (int index = 0; index < circleDataSetSize; ++index) {
262*c8dee2aaSAndroid Build Coastguard Worker CircleData& data = circleDataSet[index];
263*c8dee2aaSAndroid Build Coastguard Worker for (int idx2 = 0; idx2 < data.fPtCount; ++idx2) {
264*c8dee2aaSAndroid Build Coastguard Worker data.fShortPts[idx2] = data.fPts.fPts[idx2].asSkPoint();
265*c8dee2aaSAndroid Build Coastguard Worker }
266*c8dee2aaSAndroid Build Coastguard Worker switch (data.fPtCount) {
267*c8dee2aaSAndroid Build Coastguard Worker case 2:
268*c8dee2aaSAndroid Build Coastguard Worker contour.addLine(data.fShortPts);
269*c8dee2aaSAndroid Build Coastguard Worker break;
270*c8dee2aaSAndroid Build Coastguard Worker case 3:
271*c8dee2aaSAndroid Build Coastguard Worker contour.addQuad(data.fShortPts);
272*c8dee2aaSAndroid Build Coastguard Worker break;
273*c8dee2aaSAndroid Build Coastguard Worker case 4:
274*c8dee2aaSAndroid Build Coastguard Worker contour.addCubic(data.fShortPts);
275*c8dee2aaSAndroid Build Coastguard Worker break;
276*c8dee2aaSAndroid Build Coastguard Worker }
277*c8dee2aaSAndroid Build Coastguard Worker }
278*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* first = contour.first();
279*c8dee2aaSAndroid Build Coastguard Worker first->debugAddAngle(0, 1);
280*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* next = first->next();
281*c8dee2aaSAndroid Build Coastguard Worker next->debugAddAngle(0, 1);
282*c8dee2aaSAndroid Build Coastguard Worker PathOpsAngleTester::Orderable(*first->debugLastAngle(), *next->debugLastAngle());
283*c8dee2aaSAndroid Build Coastguard Worker }
284*c8dee2aaSAndroid Build Coastguard Worker
285*c8dee2aaSAndroid Build Coastguard Worker struct IntersectData {
286*c8dee2aaSAndroid Build Coastguard Worker const CubicPts fPts;
287*c8dee2aaSAndroid Build Coastguard Worker const int fPtCount;
288*c8dee2aaSAndroid Build Coastguard Worker double fTStart;
289*c8dee2aaSAndroid Build Coastguard Worker double fTEnd;
290*c8dee2aaSAndroid Build Coastguard Worker SkPoint fShortPts[4];
291*c8dee2aaSAndroid Build Coastguard Worker };
292*c8dee2aaSAndroid Build Coastguard Worker
293*c8dee2aaSAndroid Build Coastguard Worker static IntersectData intersectDataSet1[] = {
294*c8dee2aaSAndroid Build Coastguard Worker { {{{322.935669,231.030273}, {312.832214,220.393295}, {312.832214,203.454178}}}, 3,
295*c8dee2aaSAndroid Build Coastguard Worker 0.865309956, 0.154740299, {} },
296*c8dee2aaSAndroid Build Coastguard Worker { {{{322.12738,233.397751}, {295.718353,159.505829}}}, 2,
297*c8dee2aaSAndroid Build Coastguard Worker 0.345028807, 0.0786326511, {} },
298*c8dee2aaSAndroid Build Coastguard Worker { {{{322.935669,231.030273}, {312.832214,220.393295}, {312.832214,203.454178}}}, 3,
299*c8dee2aaSAndroid Build Coastguard Worker 0.865309956, 1, {} },
300*c8dee2aaSAndroid Build Coastguard Worker { {{{322.12738,233.397751}, {295.718353,159.505829}}}, 2,
301*c8dee2aaSAndroid Build Coastguard Worker 0.345028807, 1, {} },
302*c8dee2aaSAndroid Build Coastguard Worker };
303*c8dee2aaSAndroid Build Coastguard Worker
304*c8dee2aaSAndroid Build Coastguard Worker static IntersectData intersectDataSet2[] = {
305*c8dee2aaSAndroid Build Coastguard Worker { {{{364.390686,157.898193}, {375.281769,136.674606}, {396.039917,136.674606}}}, 3,
306*c8dee2aaSAndroid Build Coastguard Worker 0.578520747, 1, {} },
307*c8dee2aaSAndroid Build Coastguard Worker { {{{364.390686,157.898193}, {375.281769,136.674606}, {396.039917,136.674606}}}, 3,
308*c8dee2aaSAndroid Build Coastguard Worker 0.578520747, 0.536512973, {} },
309*c8dee2aaSAndroid Build Coastguard Worker { {{{366.608826,151.196014}, {378.803101,136.674606}, {398.164948,136.674606}}}, 3,
310*c8dee2aaSAndroid Build Coastguard Worker 0.490456543, 1, {} },
311*c8dee2aaSAndroid Build Coastguard Worker };
312*c8dee2aaSAndroid Build Coastguard Worker
313*c8dee2aaSAndroid Build Coastguard Worker static IntersectData intersectDataSet3[] = {
314*c8dee2aaSAndroid Build Coastguard Worker { {{{2.000000,0.000000}, {1.33333333,0.66666667}}}, 2, 1, 0, {} },
315*c8dee2aaSAndroid Build Coastguard Worker { {{{1.33333333,0.66666667}, {0.000000,2.000000}}}, 2, 0, 0.25, {} },
316*c8dee2aaSAndroid Build Coastguard Worker { {{{2.000000,2.000000}, {1.33333333,0.66666667}}}, 2, 1, 0, {} },
317*c8dee2aaSAndroid Build Coastguard Worker };
318*c8dee2aaSAndroid Build Coastguard Worker
319*c8dee2aaSAndroid Build Coastguard Worker static IntersectData intersectDataSet4[] = {
320*c8dee2aaSAndroid Build Coastguard Worker { {{{1.3333333,0.6666667}, {0.000,2.000}}}, 2, 0.250000006, 0, {} },
321*c8dee2aaSAndroid Build Coastguard Worker { {{{1.000,0.000}, {1.000,1.000}}}, 2, 1, 0, {} },
322*c8dee2aaSAndroid Build Coastguard Worker { {{{1.000,1.000}, {0.000,0.000}}}, 2, 0, 1, {} },
323*c8dee2aaSAndroid Build Coastguard Worker };
324*c8dee2aaSAndroid Build Coastguard Worker
325*c8dee2aaSAndroid Build Coastguard Worker static IntersectData intersectDataSet5[] = {
326*c8dee2aaSAndroid Build Coastguard Worker { {{{0.000,0.000}, {1.000,0.000}, {1.000,1.000}}}, 3, 1, 0.666666667, {} },
327*c8dee2aaSAndroid Build Coastguard Worker { {{{0.000,0.000}, {2.000,1.000}, {0.000,2.000}}}, 3, 0.5, 1, {} },
328*c8dee2aaSAndroid Build Coastguard Worker { {{{0.000,0.000}, {2.000,1.000}, {0.000,2.000}}}, 3, 0.5, 0, {} },
329*c8dee2aaSAndroid Build Coastguard Worker };
330*c8dee2aaSAndroid Build Coastguard Worker
331*c8dee2aaSAndroid Build Coastguard Worker static IntersectData intersectDataSet6[] = { // pathops_visualizer.htm:3658
332*c8dee2aaSAndroid Build Coastguard Worker { {{{0.000,1.000}, {3.000,4.000}, {1.000,0.000}, {3.000,0.000}}}, 4, 0.0925339054, 0, {} }, // pathops_visualizer.htm:3616
333*c8dee2aaSAndroid Build Coastguard Worker { {{{0.000,1.000}, {0.000,3.000}, {1.000,0.000}, {4.000,3.000}}}, 4, 0.453872386, 0, {} }, // pathops_visualizer.htm:3616
334*c8dee2aaSAndroid Build Coastguard Worker { {{{0.000,1.000}, {3.000,4.000}, {1.000,0.000}, {3.000,0.000}}}, 4, 0.0925339054, 0.417096368, {} }, // pathops_visualizer.htm:3616
335*c8dee2aaSAndroid Build Coastguard Worker };
336*c8dee2aaSAndroid Build Coastguard Worker
337*c8dee2aaSAndroid Build Coastguard Worker static IntersectData intersectDataSet7[] = { // pathops_visualizer.htm:3748
338*c8dee2aaSAndroid Build Coastguard Worker { {{{2.000,1.000}, {0.000,1.000}}}, 2, 0.5, 0, {} }, // pathops_visualizer.htm:3706
339*c8dee2aaSAndroid Build Coastguard Worker { {{{2.000,0.000}, {0.000,2.000}}}, 2, 0.5, 1, {} }, // pathops_visualizer.htm:3706
340*c8dee2aaSAndroid Build Coastguard Worker { {{{0.000,1.000}, {0.000,2.000}, {2.000,0.000}, {2.000,1.000}}}, 4, 0.5, 1, {} }, // pathops_visualizer.htm:3706
341*c8dee2aaSAndroid Build Coastguard Worker }; //
342*c8dee2aaSAndroid Build Coastguard Worker
343*c8dee2aaSAndroid Build Coastguard Worker static IntersectData intersectDataSet8[] = { // pathops_visualizer.htm:4194
344*c8dee2aaSAndroid Build Coastguard Worker { {{{0.000,1.000}, {2.000,3.000}, {5.000,1.000}, {4.000,3.000}}}, 4, 0.311007457, 0.285714286, {} }, // pathops_visualizer.htm:4152
345*c8dee2aaSAndroid Build Coastguard Worker { {{{1.000,5.000}, {3.000,4.000}, {1.000,0.000}, {3.000,2.000}}}, 4, 0.589885081, 0.999982974, {} }, // pathops_visualizer.htm:4152
346*c8dee2aaSAndroid Build Coastguard Worker { {{{1.000,5.000}, {3.000,4.000}, {1.000,0.000}, {3.000,2.000}}}, 4, 0.589885081, 0.576935809, {} }, // pathops_visualizer.htm:4152
347*c8dee2aaSAndroid Build Coastguard Worker }; //
348*c8dee2aaSAndroid Build Coastguard Worker
349*c8dee2aaSAndroid Build Coastguard Worker static IntersectData intersectDataSet9[] = { // pathops_visualizer.htm:4142
350*c8dee2aaSAndroid Build Coastguard Worker { {{{0.000,1.000}, {2.000,3.000}, {5.000,1.000}, {4.000,3.000}}}, 4, 0.476627072, 0.311007457, {} }, // pathops_visualizer.htm:4100
351*c8dee2aaSAndroid Build Coastguard Worker { {{{1.000,5.000}, {3.000,4.000}, {1.000,0.000}, {3.000,2.000}}}, 4, 0.999982974, 1, {} }, // pathops_visualizer.htm:4100
352*c8dee2aaSAndroid Build Coastguard Worker { {{{0.000,1.000}, {2.000,3.000}, {5.000,1.000}, {4.000,3.000}}}, 4, 0.476627072, 1, {} }, // pathops_visualizer.htm:4100
353*c8dee2aaSAndroid Build Coastguard Worker }; //
354*c8dee2aaSAndroid Build Coastguard Worker
355*c8dee2aaSAndroid Build Coastguard Worker static IntersectData intersectDataSet10[] = { // pathops_visualizer.htm:4186
356*c8dee2aaSAndroid Build Coastguard Worker { {{{0.000,1.000}, {1.000,6.000}, {1.000,0.000}, {1.000,0.000}}}, 4, 0.788195121, 0.726275769, {} }, // pathops_visualizer.htm:4144
357*c8dee2aaSAndroid Build Coastguard Worker { {{{0.000,1.000}, {0.000,1.000}, {1.000,0.000}, {6.000,1.000}}}, 4, 0.473378977, 1, {} }, // pathops_visualizer.htm:4144
358*c8dee2aaSAndroid Build Coastguard Worker { {{{0.000,1.000}, {1.000,6.000}, {1.000,0.000}, {1.000,0.000}}}, 4, 0.788195121, 1, {} }, // pathops_visualizer.htm:4144
359*c8dee2aaSAndroid Build Coastguard Worker }; //
360*c8dee2aaSAndroid Build Coastguard Worker
361*c8dee2aaSAndroid Build Coastguard Worker static IntersectData intersectDataSet11[] = { // pathops_visualizer.htm:4704
362*c8dee2aaSAndroid Build Coastguard Worker { {{{979.305,561.000}, {1036.695,291.000}}}, 2, 0.888888874, 0.11111108, {} }, // pathops_visualizer.htm:4662
363*c8dee2aaSAndroid Build Coastguard Worker { {{{1006.695,291.000}, {1023.264,291.000}, {1033.840,304.431}, {1030.318,321.000}}}, 4, 1, 0, {} }, // pathops_visualizer.htm:4662
364*c8dee2aaSAndroid Build Coastguard Worker { {{{979.305,561.000}, {1036.695,291.000}}}, 2, 0.888888874, 1, {} }, // pathops_visualizer.htm:4662
365*c8dee2aaSAndroid Build Coastguard Worker }; //
366*c8dee2aaSAndroid Build Coastguard Worker
367*c8dee2aaSAndroid Build Coastguard Worker static IntersectData intersectDataSet12[] = { // pathops_visualizer.htm:5481
368*c8dee2aaSAndroid Build Coastguard Worker { {{{67.000,912.000}, {67.000,913.000}}}, 2, 1, 0, {} }, // pathops_visualizer.htm:5439
369*c8dee2aaSAndroid Build Coastguard Worker { {{{67.000,913.000}, {67.000,917.389}, {67.224,921.726}, {67.662,926.000}}}, 4, 0, 1, {} }, // pathops_visualizer.htm:5439
370*c8dee2aaSAndroid Build Coastguard Worker { {{{194.000,1041.000}, {123.860,1041.000}, {67.000,983.692}, {67.000,913.000}}}, 4, 1, 0, {} }, // pathops_visualizer.htm:5439
371*c8dee2aaSAndroid Build Coastguard Worker }; //
372*c8dee2aaSAndroid Build Coastguard Worker
373*c8dee2aaSAndroid Build Coastguard Worker static IntersectData intersectDataSet13[] = { // pathops_visualizer.htm:5735
374*c8dee2aaSAndroid Build Coastguard Worker { {{{6.000,0.000}, {0.000,4.000}}}, 2, 0.625, 0.25, {} }, // pathops_visualizer.htm:5693
375*c8dee2aaSAndroid Build Coastguard Worker { {{{0.000,1.000}, {0.000,6.000}, {4.000,0.000}, {6.000,1.000}}}, 4, 0.5, 0.833333333, {} }, // pathops_visualizer.htm:5693
376*c8dee2aaSAndroid Build Coastguard Worker { {{{0.000,1.000}, {0.000,6.000}, {4.000,0.000}, {6.000,1.000}}}, 4, 0.5, 0.379043969, {} }, // pathops_visualizer.htm:5693
377*c8dee2aaSAndroid Build Coastguard Worker }; //
378*c8dee2aaSAndroid Build Coastguard Worker
379*c8dee2aaSAndroid Build Coastguard Worker static IntersectData intersectDataSet14[] = { // pathops_visualizer.htm:5875
380*c8dee2aaSAndroid Build Coastguard Worker { {{{0.000,1.000}, {4.000,6.000}, {2.000,1.000}, {2.000,0.000}}}, 4, 0.0756502183, 0.0594570973, {} }, // pathops_visualizer.htm:5833
381*c8dee2aaSAndroid Build Coastguard Worker { {{{1.000,2.000}, {0.000,2.000}, {1.000,0.000}, {6.000,4.000}}}, 4, 0.0756502184, 0, {} }, // pathops_visualizer.htm:5833
382*c8dee2aaSAndroid Build Coastguard Worker { {{{0.000,1.000}, {4.000,6.000}, {2.000,1.000}, {2.000,0.000}}}, 4, 0.0756502183, 0.531917258, {} }, // pathops_visualizer.htm:5833
383*c8dee2aaSAndroid Build Coastguard Worker }; //
384*c8dee2aaSAndroid Build Coastguard Worker
385*c8dee2aaSAndroid Build Coastguard Worker static IntersectData intersectDataSet15[] = { // pathops_visualizer.htm:6580
386*c8dee2aaSAndroid Build Coastguard Worker { {{{490.435,879.407}, {405.593,909.436}}}, 2, 0.500554405, 1, {} }, // pathops_visualizer.htm:6538
387*c8dee2aaSAndroid Build Coastguard Worker { {{{447.967,894.438}, {448.007,894.424}, {448.014,894.422}}}, 3, 0, 1, {} }, // pathops_visualizer.htm:6538
388*c8dee2aaSAndroid Build Coastguard Worker { {{{490.435,879.407}, {405.593,909.436}}}, 2, 0.500554405, 0.500000273, {} }, // pathops_visualizer.htm:6538
389*c8dee2aaSAndroid Build Coastguard Worker }; //
390*c8dee2aaSAndroid Build Coastguard Worker
391*c8dee2aaSAndroid Build Coastguard Worker static IntersectData intersectDataSet16[] = { // pathops_visualizer.htm:7419
392*c8dee2aaSAndroid Build Coastguard Worker { {{{1.000,4.000}, {4.000,5.000}, {3.000,2.000}, {6.000,3.000}}}, 4, 0.5, 0, {} }, // pathops_visualizer.htm:7377
393*c8dee2aaSAndroid Build Coastguard Worker { {{{2.000,3.000}, {3.000,6.000}, {4.000,1.000}, {5.000,4.000}}}, 4, 0.5, 0.112701665, {} }, // pathops_visualizer.htm:7377
394*c8dee2aaSAndroid Build Coastguard Worker { {{{5.000,4.000}, {2.000,3.000}}}, 2, 0.5, 0, {} }, // pathops_visualizer.htm:7377
395*c8dee2aaSAndroid Build Coastguard Worker }; //
396*c8dee2aaSAndroid Build Coastguard Worker
397*c8dee2aaSAndroid Build Coastguard Worker // from skpi_gino_com_16
398*c8dee2aaSAndroid Build Coastguard Worker static IntersectData intersectDataSet17[] = {
399*c8dee2aaSAndroid Build Coastguard Worker { /*seg=7*/ {{{270.974121f, 770.025879f}, {234.948273f, 734}, {184, 734}}}
400*c8dee2aaSAndroid Build Coastguard Worker , 3, 0.74590454, 0.547660352, {} },
401*c8dee2aaSAndroid Build Coastguard Worker { /*seg=8*/ {{{185, 734}, {252.93103f, 734}, {308, 789.06897f}, {308, 857}}}
402*c8dee2aaSAndroid Build Coastguard Worker , 4, 0.12052623, 0, {} },
403*c8dee2aaSAndroid Build Coastguard Worker { /*seg=7*/ {{{270.974121f, 770.025879f}, {234.948273f, 734}, {184, 734}}}
404*c8dee2aaSAndroid Build Coastguard Worker , 3, 0.74590454, 1, {} },
405*c8dee2aaSAndroid Build Coastguard Worker };
406*c8dee2aaSAndroid Build Coastguard Worker
407*c8dee2aaSAndroid Build Coastguard Worker static IntersectData intersectDataSet18[] = {
408*c8dee2aaSAndroid Build Coastguard Worker { /*seg=7*/ {{{270.974121f, 770.025879f}, {234.948273f, 734}, {184, 734}}}
409*c8dee2aaSAndroid Build Coastguard Worker , 3, 0.74590454, 1, {} },
410*c8dee2aaSAndroid Build Coastguard Worker { /*seg=8*/ {{{185, 734}, {252.93103f, 734}, {308, 789.06897f}, {308, 857}}}
411*c8dee2aaSAndroid Build Coastguard Worker , 4, 0.12052623, 0.217351928, {} },
412*c8dee2aaSAndroid Build Coastguard Worker { /*seg=7*/ {{{270.974121f, 770.025879f}, {234.948273f, 734}, {184, 734}}}
413*c8dee2aaSAndroid Build Coastguard Worker , 3, 0.74590454, 0.547660352, {} },
414*c8dee2aaSAndroid Build Coastguard Worker };
415*c8dee2aaSAndroid Build Coastguard Worker
416*c8dee2aaSAndroid Build Coastguard Worker static IntersectData intersectDataSet19[] = {
417*c8dee2aaSAndroid Build Coastguard Worker { /*seg=1*/ {{{0, 1}, {3, 5}, {2, 1}, {3, 1}}}
418*c8dee2aaSAndroid Build Coastguard Worker , 4, 0.135148995, 0.134791946, {} },
419*c8dee2aaSAndroid Build Coastguard Worker { /*seg=3*/ {{{1, 2}, {1, 2.15061641f}, {1, 2.21049166f}, {1.01366711f, 2.21379328f}}}
420*c8dee2aaSAndroid Build Coastguard Worker , 4, 0.956740456, 0.894913214, {} },
421*c8dee2aaSAndroid Build Coastguard Worker { /*seg=1*/ {{{0, 1}, {3, 5}, {2, 1}, {3, 1}}}
422*c8dee2aaSAndroid Build Coastguard Worker , 4, 0.135148995, 0.551812363, {} },
423*c8dee2aaSAndroid Build Coastguard Worker };
424*c8dee2aaSAndroid Build Coastguard Worker
425*c8dee2aaSAndroid Build Coastguard Worker #define I(x) intersectDataSet##x
426*c8dee2aaSAndroid Build Coastguard Worker
427*c8dee2aaSAndroid Build Coastguard Worker static IntersectData* intersectDataSets[] = {
428*c8dee2aaSAndroid Build Coastguard Worker I(1), I(2), I(3), I(4), I(5), I(6), I(7), I(8), I(9), I(10),
429*c8dee2aaSAndroid Build Coastguard Worker I(11), I(12), I(13), I(14), I(15), I(16), I(17), I(18), I(19),
430*c8dee2aaSAndroid Build Coastguard Worker };
431*c8dee2aaSAndroid Build Coastguard Worker
432*c8dee2aaSAndroid Build Coastguard Worker #undef I
433*c8dee2aaSAndroid Build Coastguard Worker #define I(x) (int) std::size(intersectDataSet##x)
434*c8dee2aaSAndroid Build Coastguard Worker
435*c8dee2aaSAndroid Build Coastguard Worker static const int intersectDataSetSizes[] = {
436*c8dee2aaSAndroid Build Coastguard Worker I(1), I(2), I(3), I(4), I(5), I(6), I(7), I(8), I(9), I(10),
437*c8dee2aaSAndroid Build Coastguard Worker I(11), I(12), I(13), I(14), I(15), I(16), I(17), I(18), I(19),
438*c8dee2aaSAndroid Build Coastguard Worker };
439*c8dee2aaSAndroid Build Coastguard Worker
440*c8dee2aaSAndroid Build Coastguard Worker #undef I
441*c8dee2aaSAndroid Build Coastguard Worker
442*c8dee2aaSAndroid Build Coastguard Worker static const int intersectDataSetsSize = (int) std::size(intersectDataSetSizes);
443*c8dee2aaSAndroid Build Coastguard Worker
444*c8dee2aaSAndroid Build Coastguard Worker struct FourPoints {
445*c8dee2aaSAndroid Build Coastguard Worker SkPoint pts[4];
446*c8dee2aaSAndroid Build Coastguard Worker };
447*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(PathOpsAngleAfter,reporter)448*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(PathOpsAngleAfter, reporter) {
449*c8dee2aaSAndroid Build Coastguard Worker for (int index = intersectDataSetsSize - 1; index >= 0; --index) {
450*c8dee2aaSAndroid Build Coastguard Worker IntersectData* dataArray = intersectDataSets[index];
451*c8dee2aaSAndroid Build Coastguard Worker const int dataSize = intersectDataSetSizes[index];
452*c8dee2aaSAndroid Build Coastguard Worker for (int index2 = 0; index2 < dataSize - 2; ++index2) {
453*c8dee2aaSAndroid Build Coastguard Worker SkSTArenaAlloc<4096> alloc;
454*c8dee2aaSAndroid Build Coastguard Worker SkOpContourHead contour;
455*c8dee2aaSAndroid Build Coastguard Worker SkOpGlobalState state(&contour, &alloc SkDEBUGPARAMS(false) SkDEBUGPARAMS(nullptr));
456*c8dee2aaSAndroid Build Coastguard Worker contour.init(&state, false, false);
457*c8dee2aaSAndroid Build Coastguard Worker for (int index3 = 0; index3 < 3; ++index3) {
458*c8dee2aaSAndroid Build Coastguard Worker IntersectData& data = dataArray[index2 + index3];
459*c8dee2aaSAndroid Build Coastguard Worker SkPoint* temp = (SkPoint*) alloc.make<FourPoints>();
460*c8dee2aaSAndroid Build Coastguard Worker for (int idx2 = 0; idx2 < data.fPtCount; ++idx2) {
461*c8dee2aaSAndroid Build Coastguard Worker temp[idx2] = data.fPts.fPts[idx2].asSkPoint();
462*c8dee2aaSAndroid Build Coastguard Worker }
463*c8dee2aaSAndroid Build Coastguard Worker switch (data.fPtCount) {
464*c8dee2aaSAndroid Build Coastguard Worker case 2: {
465*c8dee2aaSAndroid Build Coastguard Worker contour.addLine(temp);
466*c8dee2aaSAndroid Build Coastguard Worker } break;
467*c8dee2aaSAndroid Build Coastguard Worker case 3: {
468*c8dee2aaSAndroid Build Coastguard Worker contour.addQuad(temp);
469*c8dee2aaSAndroid Build Coastguard Worker } break;
470*c8dee2aaSAndroid Build Coastguard Worker case 4: {
471*c8dee2aaSAndroid Build Coastguard Worker contour.addCubic(temp);
472*c8dee2aaSAndroid Build Coastguard Worker } break;
473*c8dee2aaSAndroid Build Coastguard Worker }
474*c8dee2aaSAndroid Build Coastguard Worker }
475*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* seg1 = contour.first();
476*c8dee2aaSAndroid Build Coastguard Worker seg1->debugAddAngle(dataArray[index2 + 0].fTStart, dataArray[index2 + 0].fTEnd);
477*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* seg2 = seg1->next();
478*c8dee2aaSAndroid Build Coastguard Worker seg2->debugAddAngle(dataArray[index2 + 1].fTStart, dataArray[index2 + 1].fTEnd);
479*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* seg3 = seg2->next();
480*c8dee2aaSAndroid Build Coastguard Worker seg3->debugAddAngle(dataArray[index2 + 2].fTStart, dataArray[index2 + 2].fTEnd);
481*c8dee2aaSAndroid Build Coastguard Worker SkOpAngle& angle1 = *seg1->debugLastAngle();
482*c8dee2aaSAndroid Build Coastguard Worker SkOpAngle& angle2 = *seg2->debugLastAngle();
483*c8dee2aaSAndroid Build Coastguard Worker SkOpAngle& angle3 = *seg3->debugLastAngle();
484*c8dee2aaSAndroid Build Coastguard Worker PathOpsAngleTester::SetNext(angle1, angle3);
485*c8dee2aaSAndroid Build Coastguard Worker // These data sets are seeded when the set itself fails, so likely the dataset does not
486*c8dee2aaSAndroid Build Coastguard Worker // match the expected result. The tests above return 1 when first added, but
487*c8dee2aaSAndroid Build Coastguard Worker // return 0 after the bug is fixed.
488*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(int result =) PathOpsAngleTester::After(angle2, angle1);
489*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(result == 0 || result == 1);
490*c8dee2aaSAndroid Build Coastguard Worker }
491*c8dee2aaSAndroid Build Coastguard Worker }
492*c8dee2aaSAndroid Build Coastguard Worker }
493*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(PathOpsAngleAllOnOneSide,reporter)494*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(PathOpsAngleAllOnOneSide, reporter) {
495*c8dee2aaSAndroid Build Coastguard Worker SkSTArenaAlloc<4096> allocator;
496*c8dee2aaSAndroid Build Coastguard Worker SkOpContourHead contour;
497*c8dee2aaSAndroid Build Coastguard Worker SkOpGlobalState state(&contour, &allocator SkDEBUGPARAMS(false) SkDEBUGPARAMS(nullptr));
498*c8dee2aaSAndroid Build Coastguard Worker contour.init(&state, false, false);
499*c8dee2aaSAndroid Build Coastguard Worker SkPoint conicPts[3] = {{494.37100219726562f, 224.66200256347656f},
500*c8dee2aaSAndroid Build Coastguard Worker {494.37360910682298f, 224.6729026561527f},
501*c8dee2aaSAndroid Build Coastguard Worker {494.37600708007813f, 224.68400573730469f}};
502*c8dee2aaSAndroid Build Coastguard Worker SkPoint linePts[2] = {{494.371002f, 224.662003f}, {494.375000f, 224.675995f}};
503*c8dee2aaSAndroid Build Coastguard Worker for (int i = 10; i >= 0; --i) {
504*c8dee2aaSAndroid Build Coastguard Worker SkPoint modLinePts[2] = { linePts[0], linePts[1] };
505*c8dee2aaSAndroid Build Coastguard Worker modLinePts[1].fX += i * .1f;
506*c8dee2aaSAndroid Build Coastguard Worker contour.addLine(modLinePts);
507*c8dee2aaSAndroid Build Coastguard Worker contour.addQuad(conicPts);
508*c8dee2aaSAndroid Build Coastguard Worker // contour.addConic(conicPts, 0.999935746f, &allocator);
509*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* first = contour.first();
510*c8dee2aaSAndroid Build Coastguard Worker first->debugAddAngle(0, 1);
511*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* next = first->next();
512*c8dee2aaSAndroid Build Coastguard Worker next->debugAddAngle(0, 1);
513*c8dee2aaSAndroid Build Coastguard Worker /* int result = */
514*c8dee2aaSAndroid Build Coastguard Worker PathOpsAngleTester::AllOnOneSide(*first->debugLastAngle(), *next->debugLastAngle());
515*c8dee2aaSAndroid Build Coastguard Worker // SkDebugf("i=%d result=%d\n", i , result);
516*c8dee2aaSAndroid Build Coastguard Worker }
517*c8dee2aaSAndroid Build Coastguard Worker }
518