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