1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2014 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/core/SkTSort.h" 9cb93a386Sopenharmony_ci#include "src/pathops/SkPathOpsTSect.h" 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_ci#define COINCIDENT_SPAN_COUNT 9 12cb93a386Sopenharmony_ci 13cb93a386Sopenharmony_civoid SkTCoincident::setPerp(const SkTCurve& c1, double t, 14cb93a386Sopenharmony_ci const SkDPoint& cPt, const SkTCurve& c2) { 15cb93a386Sopenharmony_ci SkDVector dxdy = c1.dxdyAtT(t); 16cb93a386Sopenharmony_ci SkDLine perp = {{ cPt, {cPt.fX + dxdy.fY, cPt.fY - dxdy.fX} }}; 17cb93a386Sopenharmony_ci SkIntersections i SkDEBUGCODE((c1.globalState())); 18cb93a386Sopenharmony_ci int used = i.intersectRay(c2, perp); 19cb93a386Sopenharmony_ci // only keep closest 20cb93a386Sopenharmony_ci if (used == 0 || used == 3) { 21cb93a386Sopenharmony_ci this->init(); 22cb93a386Sopenharmony_ci return; 23cb93a386Sopenharmony_ci } 24cb93a386Sopenharmony_ci fPerpT = i[0][0]; 25cb93a386Sopenharmony_ci fPerpPt = i.pt(0); 26cb93a386Sopenharmony_ci SkASSERT(used <= 2); 27cb93a386Sopenharmony_ci if (used == 2) { 28cb93a386Sopenharmony_ci double distSq = (fPerpPt - cPt).lengthSquared(); 29cb93a386Sopenharmony_ci double dist2Sq = (i.pt(1) - cPt).lengthSquared(); 30cb93a386Sopenharmony_ci if (dist2Sq < distSq) { 31cb93a386Sopenharmony_ci fPerpT = i[0][1]; 32cb93a386Sopenharmony_ci fPerpPt = i.pt(1); 33cb93a386Sopenharmony_ci } 34cb93a386Sopenharmony_ci } 35cb93a386Sopenharmony_ci#if DEBUG_T_SECT 36cb93a386Sopenharmony_ci SkDebugf("setPerp t=%1.9g cPt=(%1.9g,%1.9g) %s oppT=%1.9g fPerpPt=(%1.9g,%1.9g)\n", 37cb93a386Sopenharmony_ci t, cPt.fX, cPt.fY, 38cb93a386Sopenharmony_ci cPt.approximatelyEqual(fPerpPt) ? "==" : "!=", fPerpT, fPerpPt.fX, fPerpPt.fY); 39cb93a386Sopenharmony_ci#endif 40cb93a386Sopenharmony_ci fMatch = cPt.approximatelyEqual(fPerpPt); 41cb93a386Sopenharmony_ci#if DEBUG_T_SECT 42cb93a386Sopenharmony_ci if (fMatch) { 43cb93a386Sopenharmony_ci SkDebugf("%s", ""); // allow setting breakpoint 44cb93a386Sopenharmony_ci } 45cb93a386Sopenharmony_ci#endif 46cb93a386Sopenharmony_ci} 47cb93a386Sopenharmony_ci 48cb93a386Sopenharmony_civoid SkTSpan::addBounded(SkTSpan* span, SkArenaAlloc* heap) { 49cb93a386Sopenharmony_ci SkTSpanBounded* bounded = heap->make<SkTSpanBounded>(); 50cb93a386Sopenharmony_ci bounded->fBounded = span; 51cb93a386Sopenharmony_ci bounded->fNext = fBounded; 52cb93a386Sopenharmony_ci fBounded = bounded; 53cb93a386Sopenharmony_ci} 54cb93a386Sopenharmony_ci 55cb93a386Sopenharmony_ciSkTSpan* SkTSect::addFollowing( 56cb93a386Sopenharmony_ci SkTSpan* prior) { 57cb93a386Sopenharmony_ci SkTSpan* result = this->addOne(); 58cb93a386Sopenharmony_ci SkDEBUGCODE(result->debugSetGlobalState(this->globalState())); 59cb93a386Sopenharmony_ci result->fStartT = prior ? prior->fEndT : 0; 60cb93a386Sopenharmony_ci SkTSpan* next = prior ? prior->fNext : fHead; 61cb93a386Sopenharmony_ci result->fEndT = next ? next->fStartT : 1; 62cb93a386Sopenharmony_ci result->fPrev = prior; 63cb93a386Sopenharmony_ci result->fNext = next; 64cb93a386Sopenharmony_ci if (prior) { 65cb93a386Sopenharmony_ci prior->fNext = result; 66cb93a386Sopenharmony_ci } else { 67cb93a386Sopenharmony_ci fHead = result; 68cb93a386Sopenharmony_ci } 69cb93a386Sopenharmony_ci if (next) { 70cb93a386Sopenharmony_ci next->fPrev = result; 71cb93a386Sopenharmony_ci } 72cb93a386Sopenharmony_ci result->resetBounds(fCurve); 73cb93a386Sopenharmony_ci // world may not be consistent to call validate here 74cb93a386Sopenharmony_ci result->validate(); 75cb93a386Sopenharmony_ci return result; 76cb93a386Sopenharmony_ci} 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_civoid SkTSect::addForPerp(SkTSpan* span, double t) { 79cb93a386Sopenharmony_ci if (!span->hasOppT(t)) { 80cb93a386Sopenharmony_ci SkTSpan* priorSpan; 81cb93a386Sopenharmony_ci SkTSpan* opp = this->spanAtT(t, &priorSpan); 82cb93a386Sopenharmony_ci if (!opp) { 83cb93a386Sopenharmony_ci opp = this->addFollowing(priorSpan); 84cb93a386Sopenharmony_ci#if DEBUG_PERP 85cb93a386Sopenharmony_ci SkDebugf("%s priorSpan=%d t=%1.9g opp=%d\n", __FUNCTION__, priorSpan ? 86cb93a386Sopenharmony_ci priorSpan->debugID() : -1, t, opp->debugID()); 87cb93a386Sopenharmony_ci#endif 88cb93a386Sopenharmony_ci } 89cb93a386Sopenharmony_ci#if DEBUG_PERP 90cb93a386Sopenharmony_ci opp->dump(); SkDebugf("\n"); 91cb93a386Sopenharmony_ci SkDebugf("%s addBounded span=%d opp=%d\n", __FUNCTION__, priorSpan ? 92cb93a386Sopenharmony_ci priorSpan->debugID() : -1, opp->debugID()); 93cb93a386Sopenharmony_ci#endif 94cb93a386Sopenharmony_ci opp->addBounded(span, &fHeap); 95cb93a386Sopenharmony_ci span->addBounded(opp, &fHeap); 96cb93a386Sopenharmony_ci } 97cb93a386Sopenharmony_ci this->validate(); 98cb93a386Sopenharmony_ci#if DEBUG_T_SECT 99cb93a386Sopenharmony_ci span->validatePerpT(t); 100cb93a386Sopenharmony_ci#endif 101cb93a386Sopenharmony_ci} 102cb93a386Sopenharmony_ci 103cb93a386Sopenharmony_cidouble SkTSpan::closestBoundedT(const SkDPoint& pt) const { 104cb93a386Sopenharmony_ci double result = -1; 105cb93a386Sopenharmony_ci double closest = DBL_MAX; 106cb93a386Sopenharmony_ci const SkTSpanBounded* testBounded = fBounded; 107cb93a386Sopenharmony_ci while (testBounded) { 108cb93a386Sopenharmony_ci const SkTSpan* test = testBounded->fBounded; 109cb93a386Sopenharmony_ci double startDist = test->pointFirst().distanceSquared(pt); 110cb93a386Sopenharmony_ci if (closest > startDist) { 111cb93a386Sopenharmony_ci closest = startDist; 112cb93a386Sopenharmony_ci result = test->fStartT; 113cb93a386Sopenharmony_ci } 114cb93a386Sopenharmony_ci double endDist = test->pointLast().distanceSquared(pt); 115cb93a386Sopenharmony_ci if (closest > endDist) { 116cb93a386Sopenharmony_ci closest = endDist; 117cb93a386Sopenharmony_ci result = test->fEndT; 118cb93a386Sopenharmony_ci } 119cb93a386Sopenharmony_ci testBounded = testBounded->fNext; 120cb93a386Sopenharmony_ci } 121cb93a386Sopenharmony_ci SkASSERT(between(0, result, 1)); 122cb93a386Sopenharmony_ci return result; 123cb93a386Sopenharmony_ci} 124cb93a386Sopenharmony_ci 125cb93a386Sopenharmony_ci#ifdef SK_DEBUG 126cb93a386Sopenharmony_ci 127cb93a386Sopenharmony_cibool SkTSpan::debugIsBefore(const SkTSpan* span) const { 128cb93a386Sopenharmony_ci const SkTSpan* work = this; 129cb93a386Sopenharmony_ci do { 130cb93a386Sopenharmony_ci if (span == work) { 131cb93a386Sopenharmony_ci return true; 132cb93a386Sopenharmony_ci } 133cb93a386Sopenharmony_ci } while ((work = work->fNext)); 134cb93a386Sopenharmony_ci return false; 135cb93a386Sopenharmony_ci} 136cb93a386Sopenharmony_ci#endif 137cb93a386Sopenharmony_ci 138cb93a386Sopenharmony_cibool SkTSpan::contains(double t) const { 139cb93a386Sopenharmony_ci const SkTSpan* work = this; 140cb93a386Sopenharmony_ci do { 141cb93a386Sopenharmony_ci if (between(work->fStartT, t, work->fEndT)) { 142cb93a386Sopenharmony_ci return true; 143cb93a386Sopenharmony_ci } 144cb93a386Sopenharmony_ci } while ((work = work->fNext)); 145cb93a386Sopenharmony_ci return false; 146cb93a386Sopenharmony_ci} 147cb93a386Sopenharmony_ci 148cb93a386Sopenharmony_ciconst SkTSect* SkTSpan::debugOpp() const { 149cb93a386Sopenharmony_ci return SkDEBUGRELEASE(fDebugSect->debugOpp(), nullptr); 150cb93a386Sopenharmony_ci} 151cb93a386Sopenharmony_ci 152cb93a386Sopenharmony_ciSkTSpan* SkTSpan::findOppSpan( 153cb93a386Sopenharmony_ci const SkTSpan* opp) const { 154cb93a386Sopenharmony_ci SkTSpanBounded* bounded = fBounded; 155cb93a386Sopenharmony_ci while (bounded) { 156cb93a386Sopenharmony_ci SkTSpan* test = bounded->fBounded; 157cb93a386Sopenharmony_ci if (opp == test) { 158cb93a386Sopenharmony_ci return test; 159cb93a386Sopenharmony_ci } 160cb93a386Sopenharmony_ci bounded = bounded->fNext; 161cb93a386Sopenharmony_ci } 162cb93a386Sopenharmony_ci return nullptr; 163cb93a386Sopenharmony_ci} 164cb93a386Sopenharmony_ci 165cb93a386Sopenharmony_ci// returns 0 if no hull intersection 166cb93a386Sopenharmony_ci// 1 if hulls intersect 167cb93a386Sopenharmony_ci// 2 if hulls only share a common endpoint 168cb93a386Sopenharmony_ci// -1 if linear and further checking is required 169cb93a386Sopenharmony_ci 170cb93a386Sopenharmony_ciint SkTSpan::hullCheck(const SkTSpan* opp, 171cb93a386Sopenharmony_ci bool* start, bool* oppStart) { 172cb93a386Sopenharmony_ci if (fIsLinear) { 173cb93a386Sopenharmony_ci return -1; 174cb93a386Sopenharmony_ci } 175cb93a386Sopenharmony_ci bool ptsInCommon; 176cb93a386Sopenharmony_ci if (onlyEndPointsInCommon(opp, start, oppStart, &ptsInCommon)) { 177cb93a386Sopenharmony_ci SkASSERT(ptsInCommon); 178cb93a386Sopenharmony_ci return 2; 179cb93a386Sopenharmony_ci } 180cb93a386Sopenharmony_ci bool linear; 181cb93a386Sopenharmony_ci if (fPart->hullIntersects(*opp->fPart, &linear)) { 182cb93a386Sopenharmony_ci if (!linear) { // check set true if linear 183cb93a386Sopenharmony_ci return 1; 184cb93a386Sopenharmony_ci } 185cb93a386Sopenharmony_ci fIsLinear = true; 186cb93a386Sopenharmony_ci fIsLine = fPart->controlsInside(); 187cb93a386Sopenharmony_ci return ptsInCommon ? 1 : -1; 188cb93a386Sopenharmony_ci } else { // hull is not linear; check set true if intersected at the end points 189cb93a386Sopenharmony_ci return ((int) ptsInCommon) << 1; // 0 or 2 190cb93a386Sopenharmony_ci } 191cb93a386Sopenharmony_ci return 0; 192cb93a386Sopenharmony_ci} 193cb93a386Sopenharmony_ci 194cb93a386Sopenharmony_ci// OPTIMIZE ? If at_most_end_pts_in_common detects that one quad is near linear, 195cb93a386Sopenharmony_ci// use line intersection to guess a better split than 0.5 196cb93a386Sopenharmony_ci// OPTIMIZE Once at_most_end_pts_in_common detects linear, mark span so all future splits are linear 197cb93a386Sopenharmony_ci 198cb93a386Sopenharmony_ciint SkTSpan::hullsIntersect(SkTSpan* opp, 199cb93a386Sopenharmony_ci bool* start, bool* oppStart) { 200cb93a386Sopenharmony_ci if (!fBounds.intersects(opp->fBounds)) { 201cb93a386Sopenharmony_ci return 0; 202cb93a386Sopenharmony_ci } 203cb93a386Sopenharmony_ci int hullSect = this->hullCheck(opp, start, oppStart); 204cb93a386Sopenharmony_ci if (hullSect >= 0) { 205cb93a386Sopenharmony_ci return hullSect; 206cb93a386Sopenharmony_ci } 207cb93a386Sopenharmony_ci hullSect = opp->hullCheck(this, oppStart, start); 208cb93a386Sopenharmony_ci if (hullSect >= 0) { 209cb93a386Sopenharmony_ci return hullSect; 210cb93a386Sopenharmony_ci } 211cb93a386Sopenharmony_ci return -1; 212cb93a386Sopenharmony_ci} 213cb93a386Sopenharmony_ci 214cb93a386Sopenharmony_civoid SkTSpan::init(const SkTCurve& c) { 215cb93a386Sopenharmony_ci fPrev = fNext = nullptr; 216cb93a386Sopenharmony_ci fStartT = 0; 217cb93a386Sopenharmony_ci fEndT = 1; 218cb93a386Sopenharmony_ci fBounded = nullptr; 219cb93a386Sopenharmony_ci resetBounds(c); 220cb93a386Sopenharmony_ci} 221cb93a386Sopenharmony_ci 222cb93a386Sopenharmony_cibool SkTSpan::initBounds(const SkTCurve& c) { 223cb93a386Sopenharmony_ci if (SkDoubleIsNaN(fStartT) || SkDoubleIsNaN(fEndT)) { 224cb93a386Sopenharmony_ci return false; 225cb93a386Sopenharmony_ci } 226cb93a386Sopenharmony_ci c.subDivide(fStartT, fEndT, fPart); 227cb93a386Sopenharmony_ci fBounds.setBounds(*fPart); 228cb93a386Sopenharmony_ci fCoinStart.init(); 229cb93a386Sopenharmony_ci fCoinEnd.init(); 230cb93a386Sopenharmony_ci fBoundsMax = std::max(fBounds.width(), fBounds.height()); 231cb93a386Sopenharmony_ci fCollapsed = fPart->collapsed(); 232cb93a386Sopenharmony_ci fHasPerp = false; 233cb93a386Sopenharmony_ci fDeleted = false; 234cb93a386Sopenharmony_ci#if DEBUG_T_SECT 235cb93a386Sopenharmony_ci if (fCollapsed) { 236cb93a386Sopenharmony_ci SkDebugf("%s", ""); // for convenient breakpoints 237cb93a386Sopenharmony_ci } 238cb93a386Sopenharmony_ci#endif 239cb93a386Sopenharmony_ci return fBounds.valid(); 240cb93a386Sopenharmony_ci} 241cb93a386Sopenharmony_ci 242cb93a386Sopenharmony_cibool SkTSpan::linearsIntersect(SkTSpan* span) { 243cb93a386Sopenharmony_ci int result = this->linearIntersects(*span->fPart); 244cb93a386Sopenharmony_ci if (result <= 1) { 245cb93a386Sopenharmony_ci return SkToBool(result); 246cb93a386Sopenharmony_ci } 247cb93a386Sopenharmony_ci SkASSERT(span->fIsLinear); 248cb93a386Sopenharmony_ci result = span->linearIntersects(*fPart); 249cb93a386Sopenharmony_ci// SkASSERT(result <= 1); 250cb93a386Sopenharmony_ci return SkToBool(result); 251cb93a386Sopenharmony_ci} 252cb93a386Sopenharmony_ci 253cb93a386Sopenharmony_cidouble SkTSpan::linearT(const SkDPoint& pt) const { 254cb93a386Sopenharmony_ci SkDVector len = this->pointLast() - this->pointFirst(); 255cb93a386Sopenharmony_ci return fabs(len.fX) > fabs(len.fY) 256cb93a386Sopenharmony_ci ? (pt.fX - this->pointFirst().fX) / len.fX 257cb93a386Sopenharmony_ci : (pt.fY - this->pointFirst().fY) / len.fY; 258cb93a386Sopenharmony_ci} 259cb93a386Sopenharmony_ci 260cb93a386Sopenharmony_ciint SkTSpan::linearIntersects(const SkTCurve& q2) const { 261cb93a386Sopenharmony_ci // looks like q1 is near-linear 262cb93a386Sopenharmony_ci int start = 0, end = fPart->pointLast(); // the outside points are usually the extremes 263cb93a386Sopenharmony_ci if (!fPart->controlsInside()) { 264cb93a386Sopenharmony_ci double dist = 0; // if there's any question, compute distance to find best outsiders 265cb93a386Sopenharmony_ci for (int outer = 0; outer < this->pointCount() - 1; ++outer) { 266cb93a386Sopenharmony_ci for (int inner = outer + 1; inner < this->pointCount(); ++inner) { 267cb93a386Sopenharmony_ci double test = ((*fPart)[outer] - (*fPart)[inner]).lengthSquared(); 268cb93a386Sopenharmony_ci if (dist > test) { 269cb93a386Sopenharmony_ci continue; 270cb93a386Sopenharmony_ci } 271cb93a386Sopenharmony_ci dist = test; 272cb93a386Sopenharmony_ci start = outer; 273cb93a386Sopenharmony_ci end = inner; 274cb93a386Sopenharmony_ci } 275cb93a386Sopenharmony_ci } 276cb93a386Sopenharmony_ci } 277cb93a386Sopenharmony_ci // see if q2 is on one side of the line formed by the extreme points 278cb93a386Sopenharmony_ci double origX = (*fPart)[start].fX; 279cb93a386Sopenharmony_ci double origY = (*fPart)[start].fY; 280cb93a386Sopenharmony_ci double adj = (*fPart)[end].fX - origX; 281cb93a386Sopenharmony_ci double opp = (*fPart)[end].fY - origY; 282cb93a386Sopenharmony_ci double maxPart = std::max(fabs(adj), fabs(opp)); 283cb93a386Sopenharmony_ci double sign = 0; // initialization to shut up warning in release build 284cb93a386Sopenharmony_ci for (int n = 0; n < q2.pointCount(); ++n) { 285cb93a386Sopenharmony_ci double dx = q2[n].fY - origY; 286cb93a386Sopenharmony_ci double dy = q2[n].fX - origX; 287cb93a386Sopenharmony_ci double maxVal = std::max(maxPart, std::max(fabs(dx), fabs(dy))); 288cb93a386Sopenharmony_ci double test = (q2[n].fY - origY) * adj - (q2[n].fX - origX) * opp; 289cb93a386Sopenharmony_ci if (precisely_zero_when_compared_to(test, maxVal)) { 290cb93a386Sopenharmony_ci return 1; 291cb93a386Sopenharmony_ci } 292cb93a386Sopenharmony_ci if (approximately_zero_when_compared_to(test, maxVal)) { 293cb93a386Sopenharmony_ci return 3; 294cb93a386Sopenharmony_ci } 295cb93a386Sopenharmony_ci if (n == 0) { 296cb93a386Sopenharmony_ci sign = test; 297cb93a386Sopenharmony_ci continue; 298cb93a386Sopenharmony_ci } 299cb93a386Sopenharmony_ci if (test * sign < 0) { 300cb93a386Sopenharmony_ci return 1; 301cb93a386Sopenharmony_ci } 302cb93a386Sopenharmony_ci } 303cb93a386Sopenharmony_ci return 0; 304cb93a386Sopenharmony_ci} 305cb93a386Sopenharmony_ci 306cb93a386Sopenharmony_cibool SkTSpan::onlyEndPointsInCommon(const SkTSpan* opp, 307cb93a386Sopenharmony_ci bool* start, bool* oppStart, bool* ptsInCommon) { 308cb93a386Sopenharmony_ci if (opp->pointFirst() == this->pointFirst()) { 309cb93a386Sopenharmony_ci *start = *oppStart = true; 310cb93a386Sopenharmony_ci } else if (opp->pointFirst() == this->pointLast()) { 311cb93a386Sopenharmony_ci *start = false; 312cb93a386Sopenharmony_ci *oppStart = true; 313cb93a386Sopenharmony_ci } else if (opp->pointLast() == this->pointFirst()) { 314cb93a386Sopenharmony_ci *start = true; 315cb93a386Sopenharmony_ci *oppStart = false; 316cb93a386Sopenharmony_ci } else if (opp->pointLast() == this->pointLast()) { 317cb93a386Sopenharmony_ci *start = *oppStart = false; 318cb93a386Sopenharmony_ci } else { 319cb93a386Sopenharmony_ci *ptsInCommon = false; 320cb93a386Sopenharmony_ci return false; 321cb93a386Sopenharmony_ci } 322cb93a386Sopenharmony_ci *ptsInCommon = true; 323cb93a386Sopenharmony_ci const SkDPoint* otherPts[4], * oppOtherPts[4]; 324cb93a386Sopenharmony_ci// const SkDPoint* otherPts[this->pointCount() - 1], * oppOtherPts[opp->pointCount() - 1]; 325cb93a386Sopenharmony_ci int baseIndex = *start ? 0 : fPart->pointLast(); 326cb93a386Sopenharmony_ci fPart->otherPts(baseIndex, otherPts); 327cb93a386Sopenharmony_ci opp->fPart->otherPts(*oppStart ? 0 : opp->fPart->pointLast(), oppOtherPts); 328cb93a386Sopenharmony_ci const SkDPoint& base = (*fPart)[baseIndex]; 329cb93a386Sopenharmony_ci for (int o1 = 0; o1 < this->pointCount() - 1; ++o1) { 330cb93a386Sopenharmony_ci SkDVector v1 = *otherPts[o1] - base; 331cb93a386Sopenharmony_ci for (int o2 = 0; o2 < opp->pointCount() - 1; ++o2) { 332cb93a386Sopenharmony_ci SkDVector v2 = *oppOtherPts[o2] - base; 333cb93a386Sopenharmony_ci if (v2.dot(v1) >= 0) { 334cb93a386Sopenharmony_ci return false; 335cb93a386Sopenharmony_ci } 336cb93a386Sopenharmony_ci } 337cb93a386Sopenharmony_ci } 338cb93a386Sopenharmony_ci return true; 339cb93a386Sopenharmony_ci} 340cb93a386Sopenharmony_ci 341cb93a386Sopenharmony_ciSkTSpan* SkTSpan::oppT(double t) const { 342cb93a386Sopenharmony_ci SkTSpanBounded* bounded = fBounded; 343cb93a386Sopenharmony_ci while (bounded) { 344cb93a386Sopenharmony_ci SkTSpan* test = bounded->fBounded; 345cb93a386Sopenharmony_ci if (between(test->fStartT, t, test->fEndT)) { 346cb93a386Sopenharmony_ci return test; 347cb93a386Sopenharmony_ci } 348cb93a386Sopenharmony_ci bounded = bounded->fNext; 349cb93a386Sopenharmony_ci } 350cb93a386Sopenharmony_ci return nullptr; 351cb93a386Sopenharmony_ci} 352cb93a386Sopenharmony_ci 353cb93a386Sopenharmony_cibool SkTSpan::removeAllBounded() { 354cb93a386Sopenharmony_ci bool deleteSpan = false; 355cb93a386Sopenharmony_ci SkTSpanBounded* bounded = fBounded; 356cb93a386Sopenharmony_ci while (bounded) { 357cb93a386Sopenharmony_ci SkTSpan* opp = bounded->fBounded; 358cb93a386Sopenharmony_ci deleteSpan |= opp->removeBounded(this); 359cb93a386Sopenharmony_ci bounded = bounded->fNext; 360cb93a386Sopenharmony_ci } 361cb93a386Sopenharmony_ci return deleteSpan; 362cb93a386Sopenharmony_ci} 363cb93a386Sopenharmony_ci 364cb93a386Sopenharmony_cibool SkTSpan::removeBounded(const SkTSpan* opp) { 365cb93a386Sopenharmony_ci if (fHasPerp) { 366cb93a386Sopenharmony_ci bool foundStart = false; 367cb93a386Sopenharmony_ci bool foundEnd = false; 368cb93a386Sopenharmony_ci SkTSpanBounded* bounded = fBounded; 369cb93a386Sopenharmony_ci while (bounded) { 370cb93a386Sopenharmony_ci SkTSpan* test = bounded->fBounded; 371cb93a386Sopenharmony_ci if (opp != test) { 372cb93a386Sopenharmony_ci foundStart |= between(test->fStartT, fCoinStart.perpT(), test->fEndT); 373cb93a386Sopenharmony_ci foundEnd |= between(test->fStartT, fCoinEnd.perpT(), test->fEndT); 374cb93a386Sopenharmony_ci } 375cb93a386Sopenharmony_ci bounded = bounded->fNext; 376cb93a386Sopenharmony_ci } 377cb93a386Sopenharmony_ci if (!foundStart || !foundEnd) { 378cb93a386Sopenharmony_ci fHasPerp = false; 379cb93a386Sopenharmony_ci fCoinStart.init(); 380cb93a386Sopenharmony_ci fCoinEnd.init(); 381cb93a386Sopenharmony_ci } 382cb93a386Sopenharmony_ci } 383cb93a386Sopenharmony_ci SkTSpanBounded* bounded = fBounded; 384cb93a386Sopenharmony_ci SkTSpanBounded* prev = nullptr; 385cb93a386Sopenharmony_ci while (bounded) { 386cb93a386Sopenharmony_ci SkTSpanBounded* boundedNext = bounded->fNext; 387cb93a386Sopenharmony_ci if (opp == bounded->fBounded) { 388cb93a386Sopenharmony_ci if (prev) { 389cb93a386Sopenharmony_ci prev->fNext = boundedNext; 390cb93a386Sopenharmony_ci return false; 391cb93a386Sopenharmony_ci } else { 392cb93a386Sopenharmony_ci fBounded = boundedNext; 393cb93a386Sopenharmony_ci return fBounded == nullptr; 394cb93a386Sopenharmony_ci } 395cb93a386Sopenharmony_ci } 396cb93a386Sopenharmony_ci prev = bounded; 397cb93a386Sopenharmony_ci bounded = boundedNext; 398cb93a386Sopenharmony_ci } 399cb93a386Sopenharmony_ci SkOPASSERT(0); 400cb93a386Sopenharmony_ci return false; 401cb93a386Sopenharmony_ci} 402cb93a386Sopenharmony_ci 403cb93a386Sopenharmony_cibool SkTSpan::splitAt(SkTSpan* work, double t, SkArenaAlloc* heap) { 404cb93a386Sopenharmony_ci fStartT = t; 405cb93a386Sopenharmony_ci fEndT = work->fEndT; 406cb93a386Sopenharmony_ci if (fStartT == fEndT) { 407cb93a386Sopenharmony_ci fCollapsed = true; 408cb93a386Sopenharmony_ci return false; 409cb93a386Sopenharmony_ci } 410cb93a386Sopenharmony_ci work->fEndT = t; 411cb93a386Sopenharmony_ci if (work->fStartT == work->fEndT) { 412cb93a386Sopenharmony_ci work->fCollapsed = true; 413cb93a386Sopenharmony_ci return false; 414cb93a386Sopenharmony_ci } 415cb93a386Sopenharmony_ci fPrev = work; 416cb93a386Sopenharmony_ci fNext = work->fNext; 417cb93a386Sopenharmony_ci fIsLinear = work->fIsLinear; 418cb93a386Sopenharmony_ci fIsLine = work->fIsLine; 419cb93a386Sopenharmony_ci 420cb93a386Sopenharmony_ci work->fNext = this; 421cb93a386Sopenharmony_ci if (fNext) { 422cb93a386Sopenharmony_ci fNext->fPrev = this; 423cb93a386Sopenharmony_ci } 424cb93a386Sopenharmony_ci this->validate(); 425cb93a386Sopenharmony_ci SkTSpanBounded* bounded = work->fBounded; 426cb93a386Sopenharmony_ci fBounded = nullptr; 427cb93a386Sopenharmony_ci while (bounded) { 428cb93a386Sopenharmony_ci this->addBounded(bounded->fBounded, heap); 429cb93a386Sopenharmony_ci bounded = bounded->fNext; 430cb93a386Sopenharmony_ci } 431cb93a386Sopenharmony_ci bounded = fBounded; 432cb93a386Sopenharmony_ci while (bounded) { 433cb93a386Sopenharmony_ci bounded->fBounded->addBounded(this, heap); 434cb93a386Sopenharmony_ci bounded = bounded->fNext; 435cb93a386Sopenharmony_ci } 436cb93a386Sopenharmony_ci return true; 437cb93a386Sopenharmony_ci} 438cb93a386Sopenharmony_ci 439cb93a386Sopenharmony_civoid SkTSpan::validate() const { 440cb93a386Sopenharmony_ci#if DEBUG_VALIDATE 441cb93a386Sopenharmony_ci SkASSERT(this != fPrev); 442cb93a386Sopenharmony_ci SkASSERT(this != fNext); 443cb93a386Sopenharmony_ci SkASSERT(fNext == nullptr || fNext != fPrev); 444cb93a386Sopenharmony_ci SkASSERT(fNext == nullptr || this == fNext->fPrev); 445cb93a386Sopenharmony_ci SkASSERT(fPrev == nullptr || this == fPrev->fNext); 446cb93a386Sopenharmony_ci this->validateBounded(); 447cb93a386Sopenharmony_ci#endif 448cb93a386Sopenharmony_ci#if DEBUG_T_SECT 449cb93a386Sopenharmony_ci SkASSERT(fBounds.width() || fBounds.height() || fCollapsed); 450cb93a386Sopenharmony_ci SkASSERT(fBoundsMax == std::max(fBounds.width(), fBounds.height()) || fCollapsed == 0xFF); 451cb93a386Sopenharmony_ci SkASSERT(0 <= fStartT); 452cb93a386Sopenharmony_ci SkASSERT(fEndT <= 1); 453cb93a386Sopenharmony_ci SkASSERT(fStartT <= fEndT); 454cb93a386Sopenharmony_ci SkASSERT(fBounded || fCollapsed == 0xFF); 455cb93a386Sopenharmony_ci if (fHasPerp) { 456cb93a386Sopenharmony_ci if (fCoinStart.isMatch()) { 457cb93a386Sopenharmony_ci validatePerpT(fCoinStart.perpT()); 458cb93a386Sopenharmony_ci validatePerpPt(fCoinStart.perpT(), fCoinStart.perpPt()); 459cb93a386Sopenharmony_ci } 460cb93a386Sopenharmony_ci if (fCoinEnd.isMatch()) { 461cb93a386Sopenharmony_ci validatePerpT(fCoinEnd.perpT()); 462cb93a386Sopenharmony_ci validatePerpPt(fCoinEnd.perpT(), fCoinEnd.perpPt()); 463cb93a386Sopenharmony_ci } 464cb93a386Sopenharmony_ci } 465cb93a386Sopenharmony_ci#endif 466cb93a386Sopenharmony_ci} 467cb93a386Sopenharmony_ci 468cb93a386Sopenharmony_civoid SkTSpan::validateBounded() const { 469cb93a386Sopenharmony_ci#if DEBUG_VALIDATE 470cb93a386Sopenharmony_ci const SkTSpanBounded* testBounded = fBounded; 471cb93a386Sopenharmony_ci while (testBounded) { 472cb93a386Sopenharmony_ci SkDEBUGCODE(const SkTSpan* overlap = testBounded->fBounded); 473cb93a386Sopenharmony_ci SkASSERT(!overlap->fDeleted); 474cb93a386Sopenharmony_ci#if DEBUG_T_SECT 475cb93a386Sopenharmony_ci SkASSERT(((this->debugID() ^ overlap->debugID()) & 1) == 1); 476cb93a386Sopenharmony_ci SkASSERT(overlap->findOppSpan(this)); 477cb93a386Sopenharmony_ci#endif 478cb93a386Sopenharmony_ci testBounded = testBounded->fNext; 479cb93a386Sopenharmony_ci } 480cb93a386Sopenharmony_ci#endif 481cb93a386Sopenharmony_ci} 482cb93a386Sopenharmony_ci 483cb93a386Sopenharmony_civoid SkTSpan::validatePerpT(double oppT) const { 484cb93a386Sopenharmony_ci const SkTSpanBounded* testBounded = fBounded; 485cb93a386Sopenharmony_ci while (testBounded) { 486cb93a386Sopenharmony_ci const SkTSpan* overlap = testBounded->fBounded; 487cb93a386Sopenharmony_ci if (precisely_between(overlap->fStartT, oppT, overlap->fEndT)) { 488cb93a386Sopenharmony_ci return; 489cb93a386Sopenharmony_ci } 490cb93a386Sopenharmony_ci testBounded = testBounded->fNext; 491cb93a386Sopenharmony_ci } 492cb93a386Sopenharmony_ci SkASSERT(0); 493cb93a386Sopenharmony_ci} 494cb93a386Sopenharmony_ci 495cb93a386Sopenharmony_civoid SkTSpan::validatePerpPt(double t, const SkDPoint& pt) const { 496cb93a386Sopenharmony_ci SkASSERT(fDebugSect->fOppSect->fCurve.ptAtT(t) == pt); 497cb93a386Sopenharmony_ci} 498cb93a386Sopenharmony_ci 499cb93a386Sopenharmony_ciSkTSect::SkTSect(const SkTCurve& c 500cb93a386Sopenharmony_ci SkDEBUGPARAMS(SkOpGlobalState* debugGlobalState) 501cb93a386Sopenharmony_ci PATH_OPS_DEBUG_T_SECT_PARAMS(int id)) 502cb93a386Sopenharmony_ci : fCurve(c) 503cb93a386Sopenharmony_ci , fHeap(sizeof(SkTSpan) * 4) 504cb93a386Sopenharmony_ci , fCoincident(nullptr) 505cb93a386Sopenharmony_ci , fDeleted(nullptr) 506cb93a386Sopenharmony_ci , fActiveCount(0) 507cb93a386Sopenharmony_ci , fHung(false) 508cb93a386Sopenharmony_ci SkDEBUGPARAMS(fDebugGlobalState(debugGlobalState)) 509cb93a386Sopenharmony_ci PATH_OPS_DEBUG_T_SECT_PARAMS(fID(id)) 510cb93a386Sopenharmony_ci PATH_OPS_DEBUG_T_SECT_PARAMS(fDebugCount(0)) 511cb93a386Sopenharmony_ci PATH_OPS_DEBUG_T_SECT_PARAMS(fDebugAllocatedCount(0)) 512cb93a386Sopenharmony_ci{ 513cb93a386Sopenharmony_ci this->resetRemovedEnds(); 514cb93a386Sopenharmony_ci fHead = this->addOne(); 515cb93a386Sopenharmony_ci SkDEBUGCODE(fHead->debugSetGlobalState(debugGlobalState)); 516cb93a386Sopenharmony_ci fHead->init(c); 517cb93a386Sopenharmony_ci} 518cb93a386Sopenharmony_ci 519cb93a386Sopenharmony_ciSkTSpan* SkTSect::addOne() { 520cb93a386Sopenharmony_ci SkTSpan* result; 521cb93a386Sopenharmony_ci if (fDeleted) { 522cb93a386Sopenharmony_ci result = fDeleted; 523cb93a386Sopenharmony_ci fDeleted = result->fNext; 524cb93a386Sopenharmony_ci } else { 525cb93a386Sopenharmony_ci result = fHeap.make<SkTSpan>(fCurve, fHeap); 526cb93a386Sopenharmony_ci#if DEBUG_T_SECT 527cb93a386Sopenharmony_ci ++fDebugAllocatedCount; 528cb93a386Sopenharmony_ci#endif 529cb93a386Sopenharmony_ci } 530cb93a386Sopenharmony_ci result->reset(); 531cb93a386Sopenharmony_ci result->fHasPerp = false; 532cb93a386Sopenharmony_ci result->fDeleted = false; 533cb93a386Sopenharmony_ci ++fActiveCount; 534cb93a386Sopenharmony_ci PATH_OPS_DEBUG_T_SECT_CODE(result->fID = fDebugCount++ * 2 + fID); 535cb93a386Sopenharmony_ci SkDEBUGCODE(result->fDebugSect = this); 536cb93a386Sopenharmony_ci#ifdef SK_DEBUG 537cb93a386Sopenharmony_ci result->debugInit(fCurve, fHeap); 538cb93a386Sopenharmony_ci result->fCoinStart.debugInit(); 539cb93a386Sopenharmony_ci result->fCoinEnd.debugInit(); 540cb93a386Sopenharmony_ci result->fPrev = result->fNext = nullptr; 541cb93a386Sopenharmony_ci result->fBounds.debugInit(); 542cb93a386Sopenharmony_ci result->fStartT = result->fEndT = result->fBoundsMax = SK_ScalarNaN; 543cb93a386Sopenharmony_ci result->fCollapsed = result->fIsLinear = result->fIsLine = 0xFF; 544cb93a386Sopenharmony_ci#endif 545cb93a386Sopenharmony_ci return result; 546cb93a386Sopenharmony_ci} 547cb93a386Sopenharmony_ci 548cb93a386Sopenharmony_cibool SkTSect::binarySearchCoin(SkTSect* sect2, double tStart, 549cb93a386Sopenharmony_ci double tStep, double* resultT, double* oppT, SkTSpan** oppFirst) { 550cb93a386Sopenharmony_ci SkTSpan work(fCurve, fHeap); 551cb93a386Sopenharmony_ci double result = work.fStartT = work.fEndT = tStart; 552cb93a386Sopenharmony_ci SkDEBUGCODE(work.fDebugSect = this); 553cb93a386Sopenharmony_ci SkDPoint last = fCurve.ptAtT(tStart); 554cb93a386Sopenharmony_ci SkDPoint oppPt; 555cb93a386Sopenharmony_ci bool flip = false; 556cb93a386Sopenharmony_ci bool contained = false; 557cb93a386Sopenharmony_ci bool down = tStep < 0; 558cb93a386Sopenharmony_ci const SkTCurve& opp = sect2->fCurve; 559cb93a386Sopenharmony_ci do { 560cb93a386Sopenharmony_ci tStep *= 0.5; 561cb93a386Sopenharmony_ci work.fStartT += tStep; 562cb93a386Sopenharmony_ci if (flip) { 563cb93a386Sopenharmony_ci tStep = -tStep; 564cb93a386Sopenharmony_ci flip = false; 565cb93a386Sopenharmony_ci } 566cb93a386Sopenharmony_ci work.initBounds(fCurve); 567cb93a386Sopenharmony_ci if (work.fCollapsed) { 568cb93a386Sopenharmony_ci return false; 569cb93a386Sopenharmony_ci } 570cb93a386Sopenharmony_ci if (last.approximatelyEqual(work.pointFirst())) { 571cb93a386Sopenharmony_ci break; 572cb93a386Sopenharmony_ci } 573cb93a386Sopenharmony_ci last = work.pointFirst(); 574cb93a386Sopenharmony_ci work.fCoinStart.setPerp(fCurve, work.fStartT, last, opp); 575cb93a386Sopenharmony_ci if (work.fCoinStart.isMatch()) { 576cb93a386Sopenharmony_ci#if DEBUG_T_SECT 577cb93a386Sopenharmony_ci work.validatePerpPt(work.fCoinStart.perpT(), work.fCoinStart.perpPt()); 578cb93a386Sopenharmony_ci#endif 579cb93a386Sopenharmony_ci double oppTTest = work.fCoinStart.perpT(); 580cb93a386Sopenharmony_ci if (sect2->fHead->contains(oppTTest)) { 581cb93a386Sopenharmony_ci *oppT = oppTTest; 582cb93a386Sopenharmony_ci oppPt = work.fCoinStart.perpPt(); 583cb93a386Sopenharmony_ci contained = true; 584cb93a386Sopenharmony_ci if (down ? result <= work.fStartT : result >= work.fStartT) { 585cb93a386Sopenharmony_ci *oppFirst = nullptr; // signal caller to fail 586cb93a386Sopenharmony_ci return false; 587cb93a386Sopenharmony_ci } 588cb93a386Sopenharmony_ci result = work.fStartT; 589cb93a386Sopenharmony_ci continue; 590cb93a386Sopenharmony_ci } 591cb93a386Sopenharmony_ci } 592cb93a386Sopenharmony_ci tStep = -tStep; 593cb93a386Sopenharmony_ci flip = true; 594cb93a386Sopenharmony_ci } while (true); 595cb93a386Sopenharmony_ci if (!contained) { 596cb93a386Sopenharmony_ci return false; 597cb93a386Sopenharmony_ci } 598cb93a386Sopenharmony_ci if (last.approximatelyEqual(fCurve[0])) { 599cb93a386Sopenharmony_ci result = 0; 600cb93a386Sopenharmony_ci } else if (last.approximatelyEqual(this->pointLast())) { 601cb93a386Sopenharmony_ci result = 1; 602cb93a386Sopenharmony_ci } 603cb93a386Sopenharmony_ci if (oppPt.approximatelyEqual(opp[0])) { 604cb93a386Sopenharmony_ci *oppT = 0; 605cb93a386Sopenharmony_ci } else if (oppPt.approximatelyEqual(sect2->pointLast())) { 606cb93a386Sopenharmony_ci *oppT = 1; 607cb93a386Sopenharmony_ci } 608cb93a386Sopenharmony_ci *resultT = result; 609cb93a386Sopenharmony_ci return true; 610cb93a386Sopenharmony_ci} 611cb93a386Sopenharmony_ci 612cb93a386Sopenharmony_ci// OPTIMIZE ? keep a sorted list of sizes in the form of a doubly-linked list in quad span 613cb93a386Sopenharmony_ci// so that each quad sect has a pointer to the largest, and can update it as spans 614cb93a386Sopenharmony_ci// are split 615cb93a386Sopenharmony_ci 616cb93a386Sopenharmony_ciSkTSpan* SkTSect::boundsMax() { 617cb93a386Sopenharmony_ci SkTSpan* test = fHead; 618cb93a386Sopenharmony_ci SkTSpan* largest = fHead; 619cb93a386Sopenharmony_ci bool lCollapsed = largest->fCollapsed; 620cb93a386Sopenharmony_ci int safetyNet = 10000; 621cb93a386Sopenharmony_ci while ((test = test->fNext)) { 622cb93a386Sopenharmony_ci if (!--safetyNet) { 623cb93a386Sopenharmony_ci fHung = true; 624cb93a386Sopenharmony_ci return nullptr; 625cb93a386Sopenharmony_ci } 626cb93a386Sopenharmony_ci bool tCollapsed = test->fCollapsed; 627cb93a386Sopenharmony_ci if ((lCollapsed && !tCollapsed) || (lCollapsed == tCollapsed && 628cb93a386Sopenharmony_ci largest->fBoundsMax < test->fBoundsMax)) { 629cb93a386Sopenharmony_ci largest = test; 630cb93a386Sopenharmony_ci lCollapsed = test->fCollapsed; 631cb93a386Sopenharmony_ci } 632cb93a386Sopenharmony_ci } 633cb93a386Sopenharmony_ci return largest; 634cb93a386Sopenharmony_ci} 635cb93a386Sopenharmony_ci 636cb93a386Sopenharmony_cibool SkTSect::coincidentCheck(SkTSect* sect2) { 637cb93a386Sopenharmony_ci SkTSpan* first = fHead; 638cb93a386Sopenharmony_ci if (!first) { 639cb93a386Sopenharmony_ci return false; 640cb93a386Sopenharmony_ci } 641cb93a386Sopenharmony_ci SkTSpan* last, * next; 642cb93a386Sopenharmony_ci do { 643cb93a386Sopenharmony_ci int consecutive = this->countConsecutiveSpans(first, &last); 644cb93a386Sopenharmony_ci next = last->fNext; 645cb93a386Sopenharmony_ci if (consecutive < COINCIDENT_SPAN_COUNT) { 646cb93a386Sopenharmony_ci continue; 647cb93a386Sopenharmony_ci } 648cb93a386Sopenharmony_ci this->validate(); 649cb93a386Sopenharmony_ci sect2->validate(); 650cb93a386Sopenharmony_ci this->computePerpendiculars(sect2, first, last); 651cb93a386Sopenharmony_ci this->validate(); 652cb93a386Sopenharmony_ci sect2->validate(); 653cb93a386Sopenharmony_ci // check to see if a range of points are on the curve 654cb93a386Sopenharmony_ci SkTSpan* coinStart = first; 655cb93a386Sopenharmony_ci do { 656cb93a386Sopenharmony_ci bool success = this->extractCoincident(sect2, coinStart, last, &coinStart); 657cb93a386Sopenharmony_ci if (!success) { 658cb93a386Sopenharmony_ci return false; 659cb93a386Sopenharmony_ci } 660cb93a386Sopenharmony_ci } while (coinStart && !last->fDeleted); 661cb93a386Sopenharmony_ci if (!fHead || !sect2->fHead) { 662cb93a386Sopenharmony_ci break; 663cb93a386Sopenharmony_ci } 664cb93a386Sopenharmony_ci if (!next || next->fDeleted) { 665cb93a386Sopenharmony_ci break; 666cb93a386Sopenharmony_ci } 667cb93a386Sopenharmony_ci } while ((first = next)); 668cb93a386Sopenharmony_ci return true; 669cb93a386Sopenharmony_ci} 670cb93a386Sopenharmony_ci 671cb93a386Sopenharmony_civoid SkTSect::coincidentForce(SkTSect* sect2, 672cb93a386Sopenharmony_ci double start1s, double start1e) { 673cb93a386Sopenharmony_ci SkTSpan* first = fHead; 674cb93a386Sopenharmony_ci SkTSpan* last = this->tail(); 675cb93a386Sopenharmony_ci SkTSpan* oppFirst = sect2->fHead; 676cb93a386Sopenharmony_ci SkTSpan* oppLast = sect2->tail(); 677cb93a386Sopenharmony_ci if (!last || !oppLast) { 678cb93a386Sopenharmony_ci return; 679cb93a386Sopenharmony_ci } 680cb93a386Sopenharmony_ci bool deleteEmptySpans = this->updateBounded(first, last, oppFirst); 681cb93a386Sopenharmony_ci deleteEmptySpans |= sect2->updateBounded(oppFirst, oppLast, first); 682cb93a386Sopenharmony_ci this->removeSpanRange(first, last); 683cb93a386Sopenharmony_ci sect2->removeSpanRange(oppFirst, oppLast); 684cb93a386Sopenharmony_ci first->fStartT = start1s; 685cb93a386Sopenharmony_ci first->fEndT = start1e; 686cb93a386Sopenharmony_ci first->resetBounds(fCurve); 687cb93a386Sopenharmony_ci first->fCoinStart.setPerp(fCurve, start1s, fCurve[0], sect2->fCurve); 688cb93a386Sopenharmony_ci first->fCoinEnd.setPerp(fCurve, start1e, this->pointLast(), sect2->fCurve); 689cb93a386Sopenharmony_ci bool oppMatched = first->fCoinStart.perpT() < first->fCoinEnd.perpT(); 690cb93a386Sopenharmony_ci double oppStartT = first->fCoinStart.perpT() == -1 ? 0 : std::max(0., first->fCoinStart.perpT()); 691cb93a386Sopenharmony_ci double oppEndT = first->fCoinEnd.perpT() == -1 ? 1 : std::min(1., first->fCoinEnd.perpT()); 692cb93a386Sopenharmony_ci if (!oppMatched) { 693cb93a386Sopenharmony_ci using std::swap; 694cb93a386Sopenharmony_ci swap(oppStartT, oppEndT); 695cb93a386Sopenharmony_ci } 696cb93a386Sopenharmony_ci oppFirst->fStartT = oppStartT; 697cb93a386Sopenharmony_ci oppFirst->fEndT = oppEndT; 698cb93a386Sopenharmony_ci oppFirst->resetBounds(sect2->fCurve); 699cb93a386Sopenharmony_ci this->removeCoincident(first, false); 700cb93a386Sopenharmony_ci sect2->removeCoincident(oppFirst, true); 701cb93a386Sopenharmony_ci if (deleteEmptySpans) { 702cb93a386Sopenharmony_ci this->deleteEmptySpans(); 703cb93a386Sopenharmony_ci sect2->deleteEmptySpans(); 704cb93a386Sopenharmony_ci } 705cb93a386Sopenharmony_ci} 706cb93a386Sopenharmony_ci 707cb93a386Sopenharmony_cibool SkTSect::coincidentHasT(double t) { 708cb93a386Sopenharmony_ci SkTSpan* test = fCoincident; 709cb93a386Sopenharmony_ci while (test) { 710cb93a386Sopenharmony_ci if (between(test->fStartT, t, test->fEndT)) { 711cb93a386Sopenharmony_ci return true; 712cb93a386Sopenharmony_ci } 713cb93a386Sopenharmony_ci test = test->fNext; 714cb93a386Sopenharmony_ci } 715cb93a386Sopenharmony_ci return false; 716cb93a386Sopenharmony_ci} 717cb93a386Sopenharmony_ci 718cb93a386Sopenharmony_ciint SkTSect::collapsed() const { 719cb93a386Sopenharmony_ci int result = 0; 720cb93a386Sopenharmony_ci const SkTSpan* test = fHead; 721cb93a386Sopenharmony_ci while (test) { 722cb93a386Sopenharmony_ci if (test->fCollapsed) { 723cb93a386Sopenharmony_ci ++result; 724cb93a386Sopenharmony_ci } 725cb93a386Sopenharmony_ci test = test->next(); 726cb93a386Sopenharmony_ci } 727cb93a386Sopenharmony_ci return result; 728cb93a386Sopenharmony_ci} 729cb93a386Sopenharmony_ci 730cb93a386Sopenharmony_civoid SkTSect::computePerpendiculars(SkTSect* sect2, 731cb93a386Sopenharmony_ci SkTSpan* first, SkTSpan* last) { 732cb93a386Sopenharmony_ci if (!last) { 733cb93a386Sopenharmony_ci return; 734cb93a386Sopenharmony_ci } 735cb93a386Sopenharmony_ci const SkTCurve& opp = sect2->fCurve; 736cb93a386Sopenharmony_ci SkTSpan* work = first; 737cb93a386Sopenharmony_ci SkTSpan* prior = nullptr; 738cb93a386Sopenharmony_ci do { 739cb93a386Sopenharmony_ci if (!work->fHasPerp && !work->fCollapsed) { 740cb93a386Sopenharmony_ci if (prior) { 741cb93a386Sopenharmony_ci work->fCoinStart = prior->fCoinEnd; 742cb93a386Sopenharmony_ci } else { 743cb93a386Sopenharmony_ci work->fCoinStart.setPerp(fCurve, work->fStartT, work->pointFirst(), opp); 744cb93a386Sopenharmony_ci } 745cb93a386Sopenharmony_ci if (work->fCoinStart.isMatch()) { 746cb93a386Sopenharmony_ci double perpT = work->fCoinStart.perpT(); 747cb93a386Sopenharmony_ci if (sect2->coincidentHasT(perpT)) { 748cb93a386Sopenharmony_ci work->fCoinStart.init(); 749cb93a386Sopenharmony_ci } else { 750cb93a386Sopenharmony_ci sect2->addForPerp(work, perpT); 751cb93a386Sopenharmony_ci } 752cb93a386Sopenharmony_ci } 753cb93a386Sopenharmony_ci work->fCoinEnd.setPerp(fCurve, work->fEndT, work->pointLast(), opp); 754cb93a386Sopenharmony_ci if (work->fCoinEnd.isMatch()) { 755cb93a386Sopenharmony_ci double perpT = work->fCoinEnd.perpT(); 756cb93a386Sopenharmony_ci if (sect2->coincidentHasT(perpT)) { 757cb93a386Sopenharmony_ci work->fCoinEnd.init(); 758cb93a386Sopenharmony_ci } else { 759cb93a386Sopenharmony_ci sect2->addForPerp(work, perpT); 760cb93a386Sopenharmony_ci } 761cb93a386Sopenharmony_ci } 762cb93a386Sopenharmony_ci work->fHasPerp = true; 763cb93a386Sopenharmony_ci } 764cb93a386Sopenharmony_ci if (work == last) { 765cb93a386Sopenharmony_ci break; 766cb93a386Sopenharmony_ci } 767cb93a386Sopenharmony_ci prior = work; 768cb93a386Sopenharmony_ci work = work->fNext; 769cb93a386Sopenharmony_ci SkASSERT(work); 770cb93a386Sopenharmony_ci } while (true); 771cb93a386Sopenharmony_ci} 772cb93a386Sopenharmony_ci 773cb93a386Sopenharmony_ciint SkTSect::countConsecutiveSpans(SkTSpan* first, 774cb93a386Sopenharmony_ci SkTSpan** lastPtr) const { 775cb93a386Sopenharmony_ci int consecutive = 1; 776cb93a386Sopenharmony_ci SkTSpan* last = first; 777cb93a386Sopenharmony_ci do { 778cb93a386Sopenharmony_ci SkTSpan* next = last->fNext; 779cb93a386Sopenharmony_ci if (!next) { 780cb93a386Sopenharmony_ci break; 781cb93a386Sopenharmony_ci } 782cb93a386Sopenharmony_ci if (next->fStartT > last->fEndT) { 783cb93a386Sopenharmony_ci break; 784cb93a386Sopenharmony_ci } 785cb93a386Sopenharmony_ci ++consecutive; 786cb93a386Sopenharmony_ci last = next; 787cb93a386Sopenharmony_ci } while (true); 788cb93a386Sopenharmony_ci *lastPtr = last; 789cb93a386Sopenharmony_ci return consecutive; 790cb93a386Sopenharmony_ci} 791cb93a386Sopenharmony_ci 792cb93a386Sopenharmony_cibool SkTSect::hasBounded(const SkTSpan* span) const { 793cb93a386Sopenharmony_ci const SkTSpan* test = fHead; 794cb93a386Sopenharmony_ci if (!test) { 795cb93a386Sopenharmony_ci return false; 796cb93a386Sopenharmony_ci } 797cb93a386Sopenharmony_ci do { 798cb93a386Sopenharmony_ci if (test->findOppSpan(span)) { 799cb93a386Sopenharmony_ci return true; 800cb93a386Sopenharmony_ci } 801cb93a386Sopenharmony_ci } while ((test = test->next())); 802cb93a386Sopenharmony_ci return false; 803cb93a386Sopenharmony_ci} 804cb93a386Sopenharmony_ci 805cb93a386Sopenharmony_cibool SkTSect::deleteEmptySpans() { 806cb93a386Sopenharmony_ci SkTSpan* test; 807cb93a386Sopenharmony_ci SkTSpan* next = fHead; 808cb93a386Sopenharmony_ci int safetyHatch = 1000; 809cb93a386Sopenharmony_ci while ((test = next)) { 810cb93a386Sopenharmony_ci next = test->fNext; 811cb93a386Sopenharmony_ci if (!test->fBounded) { 812cb93a386Sopenharmony_ci if (!this->removeSpan(test)) { 813cb93a386Sopenharmony_ci return false; 814cb93a386Sopenharmony_ci } 815cb93a386Sopenharmony_ci } 816cb93a386Sopenharmony_ci if (--safetyHatch < 0) { 817cb93a386Sopenharmony_ci return false; 818cb93a386Sopenharmony_ci } 819cb93a386Sopenharmony_ci } 820cb93a386Sopenharmony_ci return true; 821cb93a386Sopenharmony_ci} 822cb93a386Sopenharmony_ci 823cb93a386Sopenharmony_cibool SkTSect::extractCoincident( 824cb93a386Sopenharmony_ci SkTSect* sect2, 825cb93a386Sopenharmony_ci SkTSpan* first, SkTSpan* last, 826cb93a386Sopenharmony_ci SkTSpan** result) { 827cb93a386Sopenharmony_ci first = findCoincidentRun(first, &last); 828cb93a386Sopenharmony_ci if (!first || !last) { 829cb93a386Sopenharmony_ci *result = nullptr; 830cb93a386Sopenharmony_ci return true; 831cb93a386Sopenharmony_ci } 832cb93a386Sopenharmony_ci // march outwards to find limit of coincidence from here to previous and next spans 833cb93a386Sopenharmony_ci double startT = first->fStartT; 834cb93a386Sopenharmony_ci double oppStartT SK_INIT_TO_AVOID_WARNING; 835cb93a386Sopenharmony_ci double oppEndT SK_INIT_TO_AVOID_WARNING; 836cb93a386Sopenharmony_ci SkTSpan* prev = first->fPrev; 837cb93a386Sopenharmony_ci SkASSERT(first->fCoinStart.isMatch()); 838cb93a386Sopenharmony_ci SkTSpan* oppFirst = first->findOppT(first->fCoinStart.perpT()); 839cb93a386Sopenharmony_ci SkOPASSERT(last->fCoinEnd.isMatch()); 840cb93a386Sopenharmony_ci bool oppMatched = first->fCoinStart.perpT() < first->fCoinEnd.perpT(); 841cb93a386Sopenharmony_ci double coinStart; 842cb93a386Sopenharmony_ci SkDEBUGCODE(double coinEnd); 843cb93a386Sopenharmony_ci SkTSpan* cutFirst; 844cb93a386Sopenharmony_ci if (prev && prev->fEndT == startT 845cb93a386Sopenharmony_ci && this->binarySearchCoin(sect2, startT, prev->fStartT - startT, &coinStart, 846cb93a386Sopenharmony_ci &oppStartT, &oppFirst) 847cb93a386Sopenharmony_ci && prev->fStartT < coinStart && coinStart < startT 848cb93a386Sopenharmony_ci && (cutFirst = prev->oppT(oppStartT))) { 849cb93a386Sopenharmony_ci oppFirst = cutFirst; 850cb93a386Sopenharmony_ci first = this->addSplitAt(prev, coinStart); 851cb93a386Sopenharmony_ci first->markCoincident(); 852cb93a386Sopenharmony_ci prev->fCoinEnd.markCoincident(); 853cb93a386Sopenharmony_ci if (oppFirst->fStartT < oppStartT && oppStartT < oppFirst->fEndT) { 854cb93a386Sopenharmony_ci SkTSpan* oppHalf = sect2->addSplitAt(oppFirst, oppStartT); 855cb93a386Sopenharmony_ci if (oppMatched) { 856cb93a386Sopenharmony_ci oppFirst->fCoinEnd.markCoincident(); 857cb93a386Sopenharmony_ci oppHalf->markCoincident(); 858cb93a386Sopenharmony_ci oppFirst = oppHalf; 859cb93a386Sopenharmony_ci } else { 860cb93a386Sopenharmony_ci oppFirst->markCoincident(); 861cb93a386Sopenharmony_ci oppHalf->fCoinStart.markCoincident(); 862cb93a386Sopenharmony_ci } 863cb93a386Sopenharmony_ci } 864cb93a386Sopenharmony_ci } else { 865cb93a386Sopenharmony_ci if (!oppFirst) { 866cb93a386Sopenharmony_ci return false; 867cb93a386Sopenharmony_ci } 868cb93a386Sopenharmony_ci SkDEBUGCODE(coinStart = first->fStartT); 869cb93a386Sopenharmony_ci SkDEBUGCODE(oppStartT = oppMatched ? oppFirst->fStartT : oppFirst->fEndT); 870cb93a386Sopenharmony_ci } 871cb93a386Sopenharmony_ci // FIXME: incomplete : if we're not at the end, find end of coin 872cb93a386Sopenharmony_ci SkTSpan* oppLast; 873cb93a386Sopenharmony_ci SkOPASSERT(last->fCoinEnd.isMatch()); 874cb93a386Sopenharmony_ci oppLast = last->findOppT(last->fCoinEnd.perpT()); 875cb93a386Sopenharmony_ci SkDEBUGCODE(coinEnd = last->fEndT); 876cb93a386Sopenharmony_ci#ifdef SK_DEBUG 877cb93a386Sopenharmony_ci if (!this->globalState() || !this->globalState()->debugSkipAssert()) { 878cb93a386Sopenharmony_ci oppEndT = oppMatched ? oppLast->fEndT : oppLast->fStartT; 879cb93a386Sopenharmony_ci } 880cb93a386Sopenharmony_ci#endif 881cb93a386Sopenharmony_ci if (!oppMatched) { 882cb93a386Sopenharmony_ci using std::swap; 883cb93a386Sopenharmony_ci swap(oppFirst, oppLast); 884cb93a386Sopenharmony_ci swap(oppStartT, oppEndT); 885cb93a386Sopenharmony_ci } 886cb93a386Sopenharmony_ci SkOPASSERT(oppStartT < oppEndT); 887cb93a386Sopenharmony_ci SkASSERT(coinStart == first->fStartT); 888cb93a386Sopenharmony_ci SkASSERT(coinEnd == last->fEndT); 889cb93a386Sopenharmony_ci if (!oppFirst) { 890cb93a386Sopenharmony_ci *result = nullptr; 891cb93a386Sopenharmony_ci return true; 892cb93a386Sopenharmony_ci } 893cb93a386Sopenharmony_ci SkOPASSERT(oppStartT == oppFirst->fStartT); 894cb93a386Sopenharmony_ci if (!oppLast) { 895cb93a386Sopenharmony_ci *result = nullptr; 896cb93a386Sopenharmony_ci return true; 897cb93a386Sopenharmony_ci } 898cb93a386Sopenharmony_ci SkOPASSERT(oppEndT == oppLast->fEndT); 899cb93a386Sopenharmony_ci // reduce coincident runs to single entries 900cb93a386Sopenharmony_ci this->validate(); 901cb93a386Sopenharmony_ci sect2->validate(); 902cb93a386Sopenharmony_ci bool deleteEmptySpans = this->updateBounded(first, last, oppFirst); 903cb93a386Sopenharmony_ci deleteEmptySpans |= sect2->updateBounded(oppFirst, oppLast, first); 904cb93a386Sopenharmony_ci this->removeSpanRange(first, last); 905cb93a386Sopenharmony_ci sect2->removeSpanRange(oppFirst, oppLast); 906cb93a386Sopenharmony_ci first->fEndT = last->fEndT; 907cb93a386Sopenharmony_ci first->resetBounds(this->fCurve); 908cb93a386Sopenharmony_ci first->fCoinStart.setPerp(fCurve, first->fStartT, first->pointFirst(), sect2->fCurve); 909cb93a386Sopenharmony_ci first->fCoinEnd.setPerp(fCurve, first->fEndT, first->pointLast(), sect2->fCurve); 910cb93a386Sopenharmony_ci oppStartT = first->fCoinStart.perpT(); 911cb93a386Sopenharmony_ci oppEndT = first->fCoinEnd.perpT(); 912cb93a386Sopenharmony_ci if (between(0, oppStartT, 1) && between(0, oppEndT, 1)) { 913cb93a386Sopenharmony_ci if (!oppMatched) { 914cb93a386Sopenharmony_ci using std::swap; 915cb93a386Sopenharmony_ci swap(oppStartT, oppEndT); 916cb93a386Sopenharmony_ci } 917cb93a386Sopenharmony_ci oppFirst->fStartT = oppStartT; 918cb93a386Sopenharmony_ci oppFirst->fEndT = oppEndT; 919cb93a386Sopenharmony_ci oppFirst->resetBounds(sect2->fCurve); 920cb93a386Sopenharmony_ci } 921cb93a386Sopenharmony_ci this->validateBounded(); 922cb93a386Sopenharmony_ci sect2->validateBounded(); 923cb93a386Sopenharmony_ci last = first->fNext; 924cb93a386Sopenharmony_ci if (!this->removeCoincident(first, false)) { 925cb93a386Sopenharmony_ci return false; 926cb93a386Sopenharmony_ci } 927cb93a386Sopenharmony_ci if (!sect2->removeCoincident(oppFirst, true)) { 928cb93a386Sopenharmony_ci return false; 929cb93a386Sopenharmony_ci } 930cb93a386Sopenharmony_ci if (deleteEmptySpans) { 931cb93a386Sopenharmony_ci if (!this->deleteEmptySpans() || !sect2->deleteEmptySpans()) { 932cb93a386Sopenharmony_ci *result = nullptr; 933cb93a386Sopenharmony_ci return false; 934cb93a386Sopenharmony_ci } 935cb93a386Sopenharmony_ci } 936cb93a386Sopenharmony_ci this->validate(); 937cb93a386Sopenharmony_ci sect2->validate(); 938cb93a386Sopenharmony_ci *result = last && !last->fDeleted && fHead && sect2->fHead ? last : nullptr; 939cb93a386Sopenharmony_ci return true; 940cb93a386Sopenharmony_ci} 941cb93a386Sopenharmony_ci 942cb93a386Sopenharmony_ciSkTSpan* SkTSect::findCoincidentRun( 943cb93a386Sopenharmony_ci SkTSpan* first, SkTSpan** lastPtr) { 944cb93a386Sopenharmony_ci SkTSpan* work = first; 945cb93a386Sopenharmony_ci SkTSpan* lastCandidate = nullptr; 946cb93a386Sopenharmony_ci first = nullptr; 947cb93a386Sopenharmony_ci // find the first fully coincident span 948cb93a386Sopenharmony_ci do { 949cb93a386Sopenharmony_ci if (work->fCoinStart.isMatch()) { 950cb93a386Sopenharmony_ci#if DEBUG_T_SECT 951cb93a386Sopenharmony_ci work->validatePerpT(work->fCoinStart.perpT()); 952cb93a386Sopenharmony_ci work->validatePerpPt(work->fCoinStart.perpT(), work->fCoinStart.perpPt()); 953cb93a386Sopenharmony_ci#endif 954cb93a386Sopenharmony_ci SkOPASSERT(work->hasOppT(work->fCoinStart.perpT())); 955cb93a386Sopenharmony_ci if (!work->fCoinEnd.isMatch()) { 956cb93a386Sopenharmony_ci break; 957cb93a386Sopenharmony_ci } 958cb93a386Sopenharmony_ci lastCandidate = work; 959cb93a386Sopenharmony_ci if (!first) { 960cb93a386Sopenharmony_ci first = work; 961cb93a386Sopenharmony_ci } 962cb93a386Sopenharmony_ci } else if (first && work->fCollapsed) { 963cb93a386Sopenharmony_ci *lastPtr = lastCandidate; 964cb93a386Sopenharmony_ci return first; 965cb93a386Sopenharmony_ci } else { 966cb93a386Sopenharmony_ci lastCandidate = nullptr; 967cb93a386Sopenharmony_ci SkOPASSERT(!first); 968cb93a386Sopenharmony_ci } 969cb93a386Sopenharmony_ci if (work == *lastPtr) { 970cb93a386Sopenharmony_ci return first; 971cb93a386Sopenharmony_ci } 972cb93a386Sopenharmony_ci work = work->fNext; 973cb93a386Sopenharmony_ci if (!work) { 974cb93a386Sopenharmony_ci return nullptr; 975cb93a386Sopenharmony_ci } 976cb93a386Sopenharmony_ci } while (true); 977cb93a386Sopenharmony_ci if (lastCandidate) { 978cb93a386Sopenharmony_ci *lastPtr = lastCandidate; 979cb93a386Sopenharmony_ci } 980cb93a386Sopenharmony_ci return first; 981cb93a386Sopenharmony_ci} 982cb93a386Sopenharmony_ci 983cb93a386Sopenharmony_ciint SkTSect::intersects(SkTSpan* span, 984cb93a386Sopenharmony_ci SkTSect* opp, 985cb93a386Sopenharmony_ci SkTSpan* oppSpan, int* oppResult) { 986cb93a386Sopenharmony_ci bool spanStart, oppStart; 987cb93a386Sopenharmony_ci int hullResult = span->hullsIntersect(oppSpan, &spanStart, &oppStart); 988cb93a386Sopenharmony_ci if (hullResult >= 0) { 989cb93a386Sopenharmony_ci if (hullResult == 2) { // hulls have one point in common 990cb93a386Sopenharmony_ci if (!span->fBounded || !span->fBounded->fNext) { 991cb93a386Sopenharmony_ci SkASSERT(!span->fBounded || span->fBounded->fBounded == oppSpan); 992cb93a386Sopenharmony_ci if (spanStart) { 993cb93a386Sopenharmony_ci span->fEndT = span->fStartT; 994cb93a386Sopenharmony_ci } else { 995cb93a386Sopenharmony_ci span->fStartT = span->fEndT; 996cb93a386Sopenharmony_ci } 997cb93a386Sopenharmony_ci } else { 998cb93a386Sopenharmony_ci hullResult = 1; 999cb93a386Sopenharmony_ci } 1000cb93a386Sopenharmony_ci if (!oppSpan->fBounded || !oppSpan->fBounded->fNext) { 1001cb93a386Sopenharmony_ci if (oppSpan->fBounded && oppSpan->fBounded->fBounded != span) { 1002cb93a386Sopenharmony_ci return 0; 1003cb93a386Sopenharmony_ci } 1004cb93a386Sopenharmony_ci if (oppStart) { 1005cb93a386Sopenharmony_ci oppSpan->fEndT = oppSpan->fStartT; 1006cb93a386Sopenharmony_ci } else { 1007cb93a386Sopenharmony_ci oppSpan->fStartT = oppSpan->fEndT; 1008cb93a386Sopenharmony_ci } 1009cb93a386Sopenharmony_ci *oppResult = 2; 1010cb93a386Sopenharmony_ci } else { 1011cb93a386Sopenharmony_ci *oppResult = 1; 1012cb93a386Sopenharmony_ci } 1013cb93a386Sopenharmony_ci } else { 1014cb93a386Sopenharmony_ci *oppResult = 1; 1015cb93a386Sopenharmony_ci } 1016cb93a386Sopenharmony_ci return hullResult; 1017cb93a386Sopenharmony_ci } 1018cb93a386Sopenharmony_ci if (span->fIsLine && oppSpan->fIsLine) { 1019cb93a386Sopenharmony_ci SkIntersections i; 1020cb93a386Sopenharmony_ci int sects = this->linesIntersect(span, opp, oppSpan, &i); 1021cb93a386Sopenharmony_ci if (sects == 2) { 1022cb93a386Sopenharmony_ci return *oppResult = 1; 1023cb93a386Sopenharmony_ci } 1024cb93a386Sopenharmony_ci if (!sects) { 1025cb93a386Sopenharmony_ci return -1; 1026cb93a386Sopenharmony_ci } 1027cb93a386Sopenharmony_ci this->removedEndCheck(span); 1028cb93a386Sopenharmony_ci span->fStartT = span->fEndT = i[0][0]; 1029cb93a386Sopenharmony_ci opp->removedEndCheck(oppSpan); 1030cb93a386Sopenharmony_ci oppSpan->fStartT = oppSpan->fEndT = i[1][0]; 1031cb93a386Sopenharmony_ci return *oppResult = 2; 1032cb93a386Sopenharmony_ci } 1033cb93a386Sopenharmony_ci if (span->fIsLinear || oppSpan->fIsLinear) { 1034cb93a386Sopenharmony_ci return *oppResult = (int) span->linearsIntersect(oppSpan); 1035cb93a386Sopenharmony_ci } 1036cb93a386Sopenharmony_ci return *oppResult = 1; 1037cb93a386Sopenharmony_ci} 1038cb93a386Sopenharmony_ci 1039cb93a386Sopenharmony_citemplate<typename SkTCurve> 1040cb93a386Sopenharmony_cistatic bool is_parallel(const SkDLine& thisLine, const SkTCurve& opp) { 1041cb93a386Sopenharmony_ci if (!opp.IsConic()) { 1042cb93a386Sopenharmony_ci return false; // FIXME : breaks a lot of stuff now 1043cb93a386Sopenharmony_ci } 1044cb93a386Sopenharmony_ci int finds = 0; 1045cb93a386Sopenharmony_ci SkDLine thisPerp; 1046cb93a386Sopenharmony_ci thisPerp.fPts[0].fX = thisLine.fPts[1].fX + (thisLine.fPts[1].fY - thisLine.fPts[0].fY); 1047cb93a386Sopenharmony_ci thisPerp.fPts[0].fY = thisLine.fPts[1].fY + (thisLine.fPts[0].fX - thisLine.fPts[1].fX); 1048cb93a386Sopenharmony_ci thisPerp.fPts[1] = thisLine.fPts[1]; 1049cb93a386Sopenharmony_ci SkIntersections perpRayI; 1050cb93a386Sopenharmony_ci perpRayI.intersectRay(opp, thisPerp); 1051cb93a386Sopenharmony_ci for (int pIndex = 0; pIndex < perpRayI.used(); ++pIndex) { 1052cb93a386Sopenharmony_ci finds += perpRayI.pt(pIndex).approximatelyEqual(thisPerp.fPts[1]); 1053cb93a386Sopenharmony_ci } 1054cb93a386Sopenharmony_ci thisPerp.fPts[1].fX = thisLine.fPts[0].fX + (thisLine.fPts[1].fY - thisLine.fPts[0].fY); 1055cb93a386Sopenharmony_ci thisPerp.fPts[1].fY = thisLine.fPts[0].fY + (thisLine.fPts[0].fX - thisLine.fPts[1].fX); 1056cb93a386Sopenharmony_ci thisPerp.fPts[0] = thisLine.fPts[0]; 1057cb93a386Sopenharmony_ci perpRayI.intersectRay(opp, thisPerp); 1058cb93a386Sopenharmony_ci for (int pIndex = 0; pIndex < perpRayI.used(); ++pIndex) { 1059cb93a386Sopenharmony_ci finds += perpRayI.pt(pIndex).approximatelyEqual(thisPerp.fPts[0]); 1060cb93a386Sopenharmony_ci } 1061cb93a386Sopenharmony_ci return finds >= 2; 1062cb93a386Sopenharmony_ci} 1063cb93a386Sopenharmony_ci 1064cb93a386Sopenharmony_ci// while the intersection points are sufficiently far apart: 1065cb93a386Sopenharmony_ci// construct the tangent lines from the intersections 1066cb93a386Sopenharmony_ci// find the point where the tangent line intersects the opposite curve 1067cb93a386Sopenharmony_ci 1068cb93a386Sopenharmony_ciint SkTSect::linesIntersect(SkTSpan* span, 1069cb93a386Sopenharmony_ci SkTSect* opp, 1070cb93a386Sopenharmony_ci SkTSpan* oppSpan, SkIntersections* i) { 1071cb93a386Sopenharmony_ci SkIntersections thisRayI SkDEBUGCODE((span->fDebugGlobalState)); 1072cb93a386Sopenharmony_ci SkIntersections oppRayI SkDEBUGCODE((span->fDebugGlobalState)); 1073cb93a386Sopenharmony_ci SkDLine thisLine = {{ span->pointFirst(), span->pointLast() }}; 1074cb93a386Sopenharmony_ci SkDLine oppLine = {{ oppSpan->pointFirst(), oppSpan->pointLast() }}; 1075cb93a386Sopenharmony_ci int loopCount = 0; 1076cb93a386Sopenharmony_ci double bestDistSq = DBL_MAX; 1077cb93a386Sopenharmony_ci if (!thisRayI.intersectRay(opp->fCurve, thisLine)) { 1078cb93a386Sopenharmony_ci return 0; 1079cb93a386Sopenharmony_ci } 1080cb93a386Sopenharmony_ci if (!oppRayI.intersectRay(this->fCurve, oppLine)) { 1081cb93a386Sopenharmony_ci return 0; 1082cb93a386Sopenharmony_ci } 1083cb93a386Sopenharmony_ci // if the ends of each line intersect the opposite curve, the lines are coincident 1084cb93a386Sopenharmony_ci if (thisRayI.used() > 1) { 1085cb93a386Sopenharmony_ci int ptMatches = 0; 1086cb93a386Sopenharmony_ci for (int tIndex = 0; tIndex < thisRayI.used(); ++tIndex) { 1087cb93a386Sopenharmony_ci for (int lIndex = 0; lIndex < (int) SK_ARRAY_COUNT(thisLine.fPts); ++lIndex) { 1088cb93a386Sopenharmony_ci ptMatches += thisRayI.pt(tIndex).approximatelyEqual(thisLine.fPts[lIndex]); 1089cb93a386Sopenharmony_ci } 1090cb93a386Sopenharmony_ci } 1091cb93a386Sopenharmony_ci if (ptMatches == 2 || is_parallel(thisLine, opp->fCurve)) { 1092cb93a386Sopenharmony_ci return 2; 1093cb93a386Sopenharmony_ci } 1094cb93a386Sopenharmony_ci } 1095cb93a386Sopenharmony_ci if (oppRayI.used() > 1) { 1096cb93a386Sopenharmony_ci int ptMatches = 0; 1097cb93a386Sopenharmony_ci for (int oIndex = 0; oIndex < oppRayI.used(); ++oIndex) { 1098cb93a386Sopenharmony_ci for (int lIndex = 0; lIndex < (int) SK_ARRAY_COUNT(oppLine.fPts); ++lIndex) { 1099cb93a386Sopenharmony_ci ptMatches += oppRayI.pt(oIndex).approximatelyEqual(oppLine.fPts[lIndex]); 1100cb93a386Sopenharmony_ci } 1101cb93a386Sopenharmony_ci } 1102cb93a386Sopenharmony_ci if (ptMatches == 2|| is_parallel(oppLine, this->fCurve)) { 1103cb93a386Sopenharmony_ci return 2; 1104cb93a386Sopenharmony_ci } 1105cb93a386Sopenharmony_ci } 1106cb93a386Sopenharmony_ci do { 1107cb93a386Sopenharmony_ci // pick the closest pair of points 1108cb93a386Sopenharmony_ci double closest = DBL_MAX; 1109cb93a386Sopenharmony_ci int closeIndex SK_INIT_TO_AVOID_WARNING; 1110cb93a386Sopenharmony_ci int oppCloseIndex SK_INIT_TO_AVOID_WARNING; 1111cb93a386Sopenharmony_ci for (int index = 0; index < oppRayI.used(); ++index) { 1112cb93a386Sopenharmony_ci if (!roughly_between(span->fStartT, oppRayI[0][index], span->fEndT)) { 1113cb93a386Sopenharmony_ci continue; 1114cb93a386Sopenharmony_ci } 1115cb93a386Sopenharmony_ci for (int oIndex = 0; oIndex < thisRayI.used(); ++oIndex) { 1116cb93a386Sopenharmony_ci if (!roughly_between(oppSpan->fStartT, thisRayI[0][oIndex], oppSpan->fEndT)) { 1117cb93a386Sopenharmony_ci continue; 1118cb93a386Sopenharmony_ci } 1119cb93a386Sopenharmony_ci double distSq = thisRayI.pt(index).distanceSquared(oppRayI.pt(oIndex)); 1120cb93a386Sopenharmony_ci if (closest > distSq) { 1121cb93a386Sopenharmony_ci closest = distSq; 1122cb93a386Sopenharmony_ci closeIndex = index; 1123cb93a386Sopenharmony_ci oppCloseIndex = oIndex; 1124cb93a386Sopenharmony_ci } 1125cb93a386Sopenharmony_ci } 1126cb93a386Sopenharmony_ci } 1127cb93a386Sopenharmony_ci if (closest == DBL_MAX) { 1128cb93a386Sopenharmony_ci break; 1129cb93a386Sopenharmony_ci } 1130cb93a386Sopenharmony_ci const SkDPoint& oppIPt = thisRayI.pt(oppCloseIndex); 1131cb93a386Sopenharmony_ci const SkDPoint& iPt = oppRayI.pt(closeIndex); 1132cb93a386Sopenharmony_ci if (between(span->fStartT, oppRayI[0][closeIndex], span->fEndT) 1133cb93a386Sopenharmony_ci && between(oppSpan->fStartT, thisRayI[0][oppCloseIndex], oppSpan->fEndT) 1134cb93a386Sopenharmony_ci && oppIPt.approximatelyEqual(iPt)) { 1135cb93a386Sopenharmony_ci i->merge(oppRayI, closeIndex, thisRayI, oppCloseIndex); 1136cb93a386Sopenharmony_ci return i->used(); 1137cb93a386Sopenharmony_ci } 1138cb93a386Sopenharmony_ci double distSq = oppIPt.distanceSquared(iPt); 1139cb93a386Sopenharmony_ci if (bestDistSq < distSq || ++loopCount > 5) { 1140cb93a386Sopenharmony_ci return 0; 1141cb93a386Sopenharmony_ci } 1142cb93a386Sopenharmony_ci bestDistSq = distSq; 1143cb93a386Sopenharmony_ci double oppStart = oppRayI[0][closeIndex]; 1144cb93a386Sopenharmony_ci thisLine[0] = fCurve.ptAtT(oppStart); 1145cb93a386Sopenharmony_ci thisLine[1] = thisLine[0] + fCurve.dxdyAtT(oppStart); 1146cb93a386Sopenharmony_ci if (!thisRayI.intersectRay(opp->fCurve, thisLine)) { 1147cb93a386Sopenharmony_ci break; 1148cb93a386Sopenharmony_ci } 1149cb93a386Sopenharmony_ci double start = thisRayI[0][oppCloseIndex]; 1150cb93a386Sopenharmony_ci oppLine[0] = opp->fCurve.ptAtT(start); 1151cb93a386Sopenharmony_ci oppLine[1] = oppLine[0] + opp->fCurve.dxdyAtT(start); 1152cb93a386Sopenharmony_ci if (!oppRayI.intersectRay(this->fCurve, oppLine)) { 1153cb93a386Sopenharmony_ci break; 1154cb93a386Sopenharmony_ci } 1155cb93a386Sopenharmony_ci } while (true); 1156cb93a386Sopenharmony_ci // convergence may fail if the curves are nearly coincident 1157cb93a386Sopenharmony_ci SkTCoincident oCoinS, oCoinE; 1158cb93a386Sopenharmony_ci oCoinS.setPerp(opp->fCurve, oppSpan->fStartT, oppSpan->pointFirst(), fCurve); 1159cb93a386Sopenharmony_ci oCoinE.setPerp(opp->fCurve, oppSpan->fEndT, oppSpan->pointLast(), fCurve); 1160cb93a386Sopenharmony_ci double tStart = oCoinS.perpT(); 1161cb93a386Sopenharmony_ci double tEnd = oCoinE.perpT(); 1162cb93a386Sopenharmony_ci bool swap = tStart > tEnd; 1163cb93a386Sopenharmony_ci if (swap) { 1164cb93a386Sopenharmony_ci using std::swap; 1165cb93a386Sopenharmony_ci swap(tStart, tEnd); 1166cb93a386Sopenharmony_ci } 1167cb93a386Sopenharmony_ci tStart = std::max(tStart, span->fStartT); 1168cb93a386Sopenharmony_ci tEnd = std::min(tEnd, span->fEndT); 1169cb93a386Sopenharmony_ci if (tStart > tEnd) { 1170cb93a386Sopenharmony_ci return 0; 1171cb93a386Sopenharmony_ci } 1172cb93a386Sopenharmony_ci SkDVector perpS, perpE; 1173cb93a386Sopenharmony_ci if (tStart == span->fStartT) { 1174cb93a386Sopenharmony_ci SkTCoincident coinS; 1175cb93a386Sopenharmony_ci coinS.setPerp(fCurve, span->fStartT, span->pointFirst(), opp->fCurve); 1176cb93a386Sopenharmony_ci perpS = span->pointFirst() - coinS.perpPt(); 1177cb93a386Sopenharmony_ci } else if (swap) { 1178cb93a386Sopenharmony_ci perpS = oCoinE.perpPt() - oppSpan->pointLast(); 1179cb93a386Sopenharmony_ci } else { 1180cb93a386Sopenharmony_ci perpS = oCoinS.perpPt() - oppSpan->pointFirst(); 1181cb93a386Sopenharmony_ci } 1182cb93a386Sopenharmony_ci if (tEnd == span->fEndT) { 1183cb93a386Sopenharmony_ci SkTCoincident coinE; 1184cb93a386Sopenharmony_ci coinE.setPerp(fCurve, span->fEndT, span->pointLast(), opp->fCurve); 1185cb93a386Sopenharmony_ci perpE = span->pointLast() - coinE.perpPt(); 1186cb93a386Sopenharmony_ci } else if (swap) { 1187cb93a386Sopenharmony_ci perpE = oCoinS.perpPt() - oppSpan->pointFirst(); 1188cb93a386Sopenharmony_ci } else { 1189cb93a386Sopenharmony_ci perpE = oCoinE.perpPt() - oppSpan->pointLast(); 1190cb93a386Sopenharmony_ci } 1191cb93a386Sopenharmony_ci if (perpS.dot(perpE) >= 0) { 1192cb93a386Sopenharmony_ci return 0; 1193cb93a386Sopenharmony_ci } 1194cb93a386Sopenharmony_ci SkTCoincident coinW; 1195cb93a386Sopenharmony_ci double workT = tStart; 1196cb93a386Sopenharmony_ci double tStep = tEnd - tStart; 1197cb93a386Sopenharmony_ci SkDPoint workPt; 1198cb93a386Sopenharmony_ci do { 1199cb93a386Sopenharmony_ci tStep *= 0.5; 1200cb93a386Sopenharmony_ci if (precisely_zero(tStep)) { 1201cb93a386Sopenharmony_ci return 0; 1202cb93a386Sopenharmony_ci } 1203cb93a386Sopenharmony_ci workT += tStep; 1204cb93a386Sopenharmony_ci workPt = fCurve.ptAtT(workT); 1205cb93a386Sopenharmony_ci coinW.setPerp(fCurve, workT, workPt, opp->fCurve); 1206cb93a386Sopenharmony_ci double perpT = coinW.perpT(); 1207cb93a386Sopenharmony_ci if (coinW.isMatch() ? !between(oppSpan->fStartT, perpT, oppSpan->fEndT) : perpT < 0) { 1208cb93a386Sopenharmony_ci continue; 1209cb93a386Sopenharmony_ci } 1210cb93a386Sopenharmony_ci SkDVector perpW = workPt - coinW.perpPt(); 1211cb93a386Sopenharmony_ci if ((perpS.dot(perpW) >= 0) == (tStep < 0)) { 1212cb93a386Sopenharmony_ci tStep = -tStep; 1213cb93a386Sopenharmony_ci } 1214cb93a386Sopenharmony_ci if (workPt.approximatelyEqual(coinW.perpPt())) { 1215cb93a386Sopenharmony_ci break; 1216cb93a386Sopenharmony_ci } 1217cb93a386Sopenharmony_ci } while (true); 1218cb93a386Sopenharmony_ci double oppTTest = coinW.perpT(); 1219cb93a386Sopenharmony_ci if (!opp->fHead->contains(oppTTest)) { 1220cb93a386Sopenharmony_ci return 0; 1221cb93a386Sopenharmony_ci } 1222cb93a386Sopenharmony_ci i->setMax(1); 1223cb93a386Sopenharmony_ci i->insert(workT, oppTTest, workPt); 1224cb93a386Sopenharmony_ci return 1; 1225cb93a386Sopenharmony_ci} 1226cb93a386Sopenharmony_ci 1227cb93a386Sopenharmony_cibool SkTSect::markSpanGone(SkTSpan* span) { 1228cb93a386Sopenharmony_ci if (--fActiveCount < 0) { 1229cb93a386Sopenharmony_ci return false; 1230cb93a386Sopenharmony_ci } 1231cb93a386Sopenharmony_ci span->fNext = fDeleted; 1232cb93a386Sopenharmony_ci fDeleted = span; 1233cb93a386Sopenharmony_ci SkOPASSERT(!span->fDeleted); 1234cb93a386Sopenharmony_ci span->fDeleted = true; 1235cb93a386Sopenharmony_ci return true; 1236cb93a386Sopenharmony_ci} 1237cb93a386Sopenharmony_ci 1238cb93a386Sopenharmony_cibool SkTSect::matchedDirection(double t, const SkTSect* sect2, 1239cb93a386Sopenharmony_ci double t2) const { 1240cb93a386Sopenharmony_ci SkDVector dxdy = this->fCurve.dxdyAtT(t); 1241cb93a386Sopenharmony_ci SkDVector dxdy2 = sect2->fCurve.dxdyAtT(t2); 1242cb93a386Sopenharmony_ci return dxdy.dot(dxdy2) >= 0; 1243cb93a386Sopenharmony_ci} 1244cb93a386Sopenharmony_ci 1245cb93a386Sopenharmony_civoid SkTSect::matchedDirCheck(double t, const SkTSect* sect2, 1246cb93a386Sopenharmony_ci double t2, bool* calcMatched, bool* oppMatched) const { 1247cb93a386Sopenharmony_ci if (*calcMatched) { 1248cb93a386Sopenharmony_ci SkASSERT(*oppMatched == this->matchedDirection(t, sect2, t2)); 1249cb93a386Sopenharmony_ci } else { 1250cb93a386Sopenharmony_ci *oppMatched = this->matchedDirection(t, sect2, t2); 1251cb93a386Sopenharmony_ci *calcMatched = true; 1252cb93a386Sopenharmony_ci } 1253cb93a386Sopenharmony_ci} 1254cb93a386Sopenharmony_ci 1255cb93a386Sopenharmony_civoid SkTSect::mergeCoincidence(SkTSect* sect2) { 1256cb93a386Sopenharmony_ci double smallLimit = 0; 1257cb93a386Sopenharmony_ci do { 1258cb93a386Sopenharmony_ci // find the smallest unprocessed span 1259cb93a386Sopenharmony_ci SkTSpan* smaller = nullptr; 1260cb93a386Sopenharmony_ci SkTSpan* test = fCoincident; 1261cb93a386Sopenharmony_ci do { 1262cb93a386Sopenharmony_ci if (!test) { 1263cb93a386Sopenharmony_ci return; 1264cb93a386Sopenharmony_ci } 1265cb93a386Sopenharmony_ci if (test->fStartT < smallLimit) { 1266cb93a386Sopenharmony_ci continue; 1267cb93a386Sopenharmony_ci } 1268cb93a386Sopenharmony_ci if (smaller && smaller->fEndT < test->fStartT) { 1269cb93a386Sopenharmony_ci continue; 1270cb93a386Sopenharmony_ci } 1271cb93a386Sopenharmony_ci smaller = test; 1272cb93a386Sopenharmony_ci } while ((test = test->fNext)); 1273cb93a386Sopenharmony_ci if (!smaller) { 1274cb93a386Sopenharmony_ci return; 1275cb93a386Sopenharmony_ci } 1276cb93a386Sopenharmony_ci smallLimit = smaller->fEndT; 1277cb93a386Sopenharmony_ci // find next larger span 1278cb93a386Sopenharmony_ci SkTSpan* prior = nullptr; 1279cb93a386Sopenharmony_ci SkTSpan* larger = nullptr; 1280cb93a386Sopenharmony_ci SkTSpan* largerPrior = nullptr; 1281cb93a386Sopenharmony_ci test = fCoincident; 1282cb93a386Sopenharmony_ci do { 1283cb93a386Sopenharmony_ci if (test->fStartT < smaller->fEndT) { 1284cb93a386Sopenharmony_ci continue; 1285cb93a386Sopenharmony_ci } 1286cb93a386Sopenharmony_ci SkOPASSERT(test->fStartT != smaller->fEndT); 1287cb93a386Sopenharmony_ci if (larger && larger->fStartT < test->fStartT) { 1288cb93a386Sopenharmony_ci continue; 1289cb93a386Sopenharmony_ci } 1290cb93a386Sopenharmony_ci largerPrior = prior; 1291cb93a386Sopenharmony_ci larger = test; 1292cb93a386Sopenharmony_ci } while ((void) (prior = test), (test = test->fNext)); 1293cb93a386Sopenharmony_ci if (!larger) { 1294cb93a386Sopenharmony_ci continue; 1295cb93a386Sopenharmony_ci } 1296cb93a386Sopenharmony_ci // check middle t value to see if it is coincident as well 1297cb93a386Sopenharmony_ci double midT = (smaller->fEndT + larger->fStartT) / 2; 1298cb93a386Sopenharmony_ci SkDPoint midPt = fCurve.ptAtT(midT); 1299cb93a386Sopenharmony_ci SkTCoincident coin; 1300cb93a386Sopenharmony_ci coin.setPerp(fCurve, midT, midPt, sect2->fCurve); 1301cb93a386Sopenharmony_ci if (coin.isMatch()) { 1302cb93a386Sopenharmony_ci smaller->fEndT = larger->fEndT; 1303cb93a386Sopenharmony_ci smaller->fCoinEnd = larger->fCoinEnd; 1304cb93a386Sopenharmony_ci if (largerPrior) { 1305cb93a386Sopenharmony_ci largerPrior->fNext = larger->fNext; 1306cb93a386Sopenharmony_ci largerPrior->validate(); 1307cb93a386Sopenharmony_ci } else { 1308cb93a386Sopenharmony_ci fCoincident = larger->fNext; 1309cb93a386Sopenharmony_ci } 1310cb93a386Sopenharmony_ci } 1311cb93a386Sopenharmony_ci } while (true); 1312cb93a386Sopenharmony_ci} 1313cb93a386Sopenharmony_ci 1314cb93a386Sopenharmony_ciSkTSpan* SkTSect::prev( 1315cb93a386Sopenharmony_ci SkTSpan* span) const { 1316cb93a386Sopenharmony_ci SkTSpan* result = nullptr; 1317cb93a386Sopenharmony_ci SkTSpan* test = fHead; 1318cb93a386Sopenharmony_ci while (span != test) { 1319cb93a386Sopenharmony_ci result = test; 1320cb93a386Sopenharmony_ci test = test->fNext; 1321cb93a386Sopenharmony_ci SkASSERT(test); 1322cb93a386Sopenharmony_ci } 1323cb93a386Sopenharmony_ci return result; 1324cb93a386Sopenharmony_ci} 1325cb93a386Sopenharmony_ci 1326cb93a386Sopenharmony_civoid SkTSect::recoverCollapsed() { 1327cb93a386Sopenharmony_ci SkTSpan* deleted = fDeleted; 1328cb93a386Sopenharmony_ci while (deleted) { 1329cb93a386Sopenharmony_ci SkTSpan* delNext = deleted->fNext; 1330cb93a386Sopenharmony_ci if (deleted->fCollapsed) { 1331cb93a386Sopenharmony_ci SkTSpan** spanPtr = &fHead; 1332cb93a386Sopenharmony_ci while (*spanPtr && (*spanPtr)->fEndT <= deleted->fStartT) { 1333cb93a386Sopenharmony_ci spanPtr = &(*spanPtr)->fNext; 1334cb93a386Sopenharmony_ci } 1335cb93a386Sopenharmony_ci deleted->fNext = *spanPtr; 1336cb93a386Sopenharmony_ci *spanPtr = deleted; 1337cb93a386Sopenharmony_ci } 1338cb93a386Sopenharmony_ci deleted = delNext; 1339cb93a386Sopenharmony_ci } 1340cb93a386Sopenharmony_ci} 1341cb93a386Sopenharmony_ci 1342cb93a386Sopenharmony_civoid SkTSect::removeAllBut(const SkTSpan* keep, 1343cb93a386Sopenharmony_ci SkTSpan* span, SkTSect* opp) { 1344cb93a386Sopenharmony_ci const SkTSpanBounded* testBounded = span->fBounded; 1345cb93a386Sopenharmony_ci while (testBounded) { 1346cb93a386Sopenharmony_ci SkTSpan* bounded = testBounded->fBounded; 1347cb93a386Sopenharmony_ci const SkTSpanBounded* next = testBounded->fNext; 1348cb93a386Sopenharmony_ci // may have been deleted when opp did 'remove all but' 1349cb93a386Sopenharmony_ci if (bounded != keep && !bounded->fDeleted) { 1350cb93a386Sopenharmony_ci SkAssertResult(SkDEBUGCODE(!) span->removeBounded(bounded)); 1351cb93a386Sopenharmony_ci if (bounded->removeBounded(span)) { 1352cb93a386Sopenharmony_ci opp->removeSpan(bounded); 1353cb93a386Sopenharmony_ci } 1354cb93a386Sopenharmony_ci } 1355cb93a386Sopenharmony_ci testBounded = next; 1356cb93a386Sopenharmony_ci } 1357cb93a386Sopenharmony_ci SkASSERT(!span->fDeleted); 1358cb93a386Sopenharmony_ci SkASSERT(span->findOppSpan(keep)); 1359cb93a386Sopenharmony_ci SkASSERT(keep->findOppSpan(span)); 1360cb93a386Sopenharmony_ci} 1361cb93a386Sopenharmony_ci 1362cb93a386Sopenharmony_cibool SkTSect::removeByPerpendicular(SkTSect* opp) { 1363cb93a386Sopenharmony_ci SkTSpan* test = fHead; 1364cb93a386Sopenharmony_ci SkTSpan* next; 1365cb93a386Sopenharmony_ci do { 1366cb93a386Sopenharmony_ci next = test->fNext; 1367cb93a386Sopenharmony_ci if (test->fCoinStart.perpT() < 0 || test->fCoinEnd.perpT() < 0) { 1368cb93a386Sopenharmony_ci continue; 1369cb93a386Sopenharmony_ci } 1370cb93a386Sopenharmony_ci SkDVector startV = test->fCoinStart.perpPt() - test->pointFirst(); 1371cb93a386Sopenharmony_ci SkDVector endV = test->fCoinEnd.perpPt() - test->pointLast(); 1372cb93a386Sopenharmony_ci#if DEBUG_T_SECT 1373cb93a386Sopenharmony_ci SkDebugf("%s startV=(%1.9g,%1.9g) endV=(%1.9g,%1.9g) dot=%1.9g\n", __FUNCTION__, 1374cb93a386Sopenharmony_ci startV.fX, startV.fY, endV.fX, endV.fY, startV.dot(endV)); 1375cb93a386Sopenharmony_ci#endif 1376cb93a386Sopenharmony_ci if (startV.dot(endV) <= 0) { 1377cb93a386Sopenharmony_ci continue; 1378cb93a386Sopenharmony_ci } 1379cb93a386Sopenharmony_ci if (!this->removeSpans(test, opp)) { 1380cb93a386Sopenharmony_ci return false; 1381cb93a386Sopenharmony_ci } 1382cb93a386Sopenharmony_ci } while ((test = next)); 1383cb93a386Sopenharmony_ci return true; 1384cb93a386Sopenharmony_ci} 1385cb93a386Sopenharmony_ci 1386cb93a386Sopenharmony_cibool SkTSect::removeCoincident(SkTSpan* span, bool isBetween) { 1387cb93a386Sopenharmony_ci if (!this->unlinkSpan(span)) { 1388cb93a386Sopenharmony_ci return false; 1389cb93a386Sopenharmony_ci } 1390cb93a386Sopenharmony_ci if (isBetween || between(0, span->fCoinStart.perpT(), 1)) { 1391cb93a386Sopenharmony_ci --fActiveCount; 1392cb93a386Sopenharmony_ci span->fNext = fCoincident; 1393cb93a386Sopenharmony_ci fCoincident = span; 1394cb93a386Sopenharmony_ci } else { 1395cb93a386Sopenharmony_ci this->markSpanGone(span); 1396cb93a386Sopenharmony_ci } 1397cb93a386Sopenharmony_ci return true; 1398cb93a386Sopenharmony_ci} 1399cb93a386Sopenharmony_ci 1400cb93a386Sopenharmony_civoid SkTSect::removedEndCheck(SkTSpan* span) { 1401cb93a386Sopenharmony_ci if (!span->fStartT) { 1402cb93a386Sopenharmony_ci fRemovedStartT = true; 1403cb93a386Sopenharmony_ci } 1404cb93a386Sopenharmony_ci if (1 == span->fEndT) { 1405cb93a386Sopenharmony_ci fRemovedEndT = true; 1406cb93a386Sopenharmony_ci } 1407cb93a386Sopenharmony_ci} 1408cb93a386Sopenharmony_ci 1409cb93a386Sopenharmony_cibool SkTSect::removeSpan(SkTSpan* span) {\ 1410cb93a386Sopenharmony_ci this->removedEndCheck(span); 1411cb93a386Sopenharmony_ci if (!this->unlinkSpan(span)) { 1412cb93a386Sopenharmony_ci return false; 1413cb93a386Sopenharmony_ci } 1414cb93a386Sopenharmony_ci return this->markSpanGone(span); 1415cb93a386Sopenharmony_ci} 1416cb93a386Sopenharmony_ci 1417cb93a386Sopenharmony_civoid SkTSect::removeSpanRange(SkTSpan* first, 1418cb93a386Sopenharmony_ci SkTSpan* last) { 1419cb93a386Sopenharmony_ci if (first == last) { 1420cb93a386Sopenharmony_ci return; 1421cb93a386Sopenharmony_ci } 1422cb93a386Sopenharmony_ci SkTSpan* span = first; 1423cb93a386Sopenharmony_ci SkASSERT(span); 1424cb93a386Sopenharmony_ci SkTSpan* final = last->fNext; 1425cb93a386Sopenharmony_ci SkTSpan* next = span->fNext; 1426cb93a386Sopenharmony_ci while ((span = next) && span != final) { 1427cb93a386Sopenharmony_ci next = span->fNext; 1428cb93a386Sopenharmony_ci this->markSpanGone(span); 1429cb93a386Sopenharmony_ci } 1430cb93a386Sopenharmony_ci if (final) { 1431cb93a386Sopenharmony_ci final->fPrev = first; 1432cb93a386Sopenharmony_ci } 1433cb93a386Sopenharmony_ci first->fNext = final; 1434cb93a386Sopenharmony_ci // world may not be ready for validation here 1435cb93a386Sopenharmony_ci first->validate(); 1436cb93a386Sopenharmony_ci} 1437cb93a386Sopenharmony_ci 1438cb93a386Sopenharmony_cibool SkTSect::removeSpans(SkTSpan* span, 1439cb93a386Sopenharmony_ci SkTSect* opp) { 1440cb93a386Sopenharmony_ci SkTSpanBounded* bounded = span->fBounded; 1441cb93a386Sopenharmony_ci while (bounded) { 1442cb93a386Sopenharmony_ci SkTSpan* spanBounded = bounded->fBounded; 1443cb93a386Sopenharmony_ci SkTSpanBounded* next = bounded->fNext; 1444cb93a386Sopenharmony_ci if (span->removeBounded(spanBounded)) { // shuffles last into position 0 1445cb93a386Sopenharmony_ci this->removeSpan(span); 1446cb93a386Sopenharmony_ci } 1447cb93a386Sopenharmony_ci if (spanBounded->removeBounded(span)) { 1448cb93a386Sopenharmony_ci opp->removeSpan(spanBounded); 1449cb93a386Sopenharmony_ci } 1450cb93a386Sopenharmony_ci if (span->fDeleted && opp->hasBounded(span)) { 1451cb93a386Sopenharmony_ci return false; 1452cb93a386Sopenharmony_ci } 1453cb93a386Sopenharmony_ci bounded = next; 1454cb93a386Sopenharmony_ci } 1455cb93a386Sopenharmony_ci return true; 1456cb93a386Sopenharmony_ci} 1457cb93a386Sopenharmony_ci 1458cb93a386Sopenharmony_ciSkTSpan* SkTSect::spanAtT(double t, 1459cb93a386Sopenharmony_ci SkTSpan** priorSpan) { 1460cb93a386Sopenharmony_ci SkTSpan* test = fHead; 1461cb93a386Sopenharmony_ci SkTSpan* prev = nullptr; 1462cb93a386Sopenharmony_ci while (test && test->fEndT < t) { 1463cb93a386Sopenharmony_ci prev = test; 1464cb93a386Sopenharmony_ci test = test->fNext; 1465cb93a386Sopenharmony_ci } 1466cb93a386Sopenharmony_ci *priorSpan = prev; 1467cb93a386Sopenharmony_ci return test && test->fStartT <= t ? test : nullptr; 1468cb93a386Sopenharmony_ci} 1469cb93a386Sopenharmony_ci 1470cb93a386Sopenharmony_ciSkTSpan* SkTSect::tail() { 1471cb93a386Sopenharmony_ci SkTSpan* result = fHead; 1472cb93a386Sopenharmony_ci SkTSpan* next = fHead; 1473cb93a386Sopenharmony_ci int safetyNet = 100000; 1474cb93a386Sopenharmony_ci while ((next = next->fNext)) { 1475cb93a386Sopenharmony_ci if (!--safetyNet) { 1476cb93a386Sopenharmony_ci return nullptr; 1477cb93a386Sopenharmony_ci } 1478cb93a386Sopenharmony_ci if (next->fEndT > result->fEndT) { 1479cb93a386Sopenharmony_ci result = next; 1480cb93a386Sopenharmony_ci } 1481cb93a386Sopenharmony_ci } 1482cb93a386Sopenharmony_ci return result; 1483cb93a386Sopenharmony_ci} 1484cb93a386Sopenharmony_ci 1485cb93a386Sopenharmony_ci/* Each span has a range of opposite spans it intersects. After the span is split in two, 1486cb93a386Sopenharmony_ci adjust the range to its new size */ 1487cb93a386Sopenharmony_ci 1488cb93a386Sopenharmony_cibool SkTSect::trim(SkTSpan* span, 1489cb93a386Sopenharmony_ci SkTSect* opp) { 1490cb93a386Sopenharmony_ci FAIL_IF(!span->initBounds(fCurve)); 1491cb93a386Sopenharmony_ci const SkTSpanBounded* testBounded = span->fBounded; 1492cb93a386Sopenharmony_ci while (testBounded) { 1493cb93a386Sopenharmony_ci SkTSpan* test = testBounded->fBounded; 1494cb93a386Sopenharmony_ci const SkTSpanBounded* next = testBounded->fNext; 1495cb93a386Sopenharmony_ci int oppSects, sects = this->intersects(span, opp, test, &oppSects); 1496cb93a386Sopenharmony_ci if (sects >= 1) { 1497cb93a386Sopenharmony_ci if (oppSects == 2) { 1498cb93a386Sopenharmony_ci test->initBounds(opp->fCurve); 1499cb93a386Sopenharmony_ci opp->removeAllBut(span, test, this); 1500cb93a386Sopenharmony_ci } 1501cb93a386Sopenharmony_ci if (sects == 2) { 1502cb93a386Sopenharmony_ci span->initBounds(fCurve); 1503cb93a386Sopenharmony_ci this->removeAllBut(test, span, opp); 1504cb93a386Sopenharmony_ci return true; 1505cb93a386Sopenharmony_ci } 1506cb93a386Sopenharmony_ci } else { 1507cb93a386Sopenharmony_ci if (span->removeBounded(test)) { 1508cb93a386Sopenharmony_ci this->removeSpan(span); 1509cb93a386Sopenharmony_ci } 1510cb93a386Sopenharmony_ci if (test->removeBounded(span)) { 1511cb93a386Sopenharmony_ci opp->removeSpan(test); 1512cb93a386Sopenharmony_ci } 1513cb93a386Sopenharmony_ci } 1514cb93a386Sopenharmony_ci testBounded = next; 1515cb93a386Sopenharmony_ci } 1516cb93a386Sopenharmony_ci return true; 1517cb93a386Sopenharmony_ci} 1518cb93a386Sopenharmony_ci 1519cb93a386Sopenharmony_cibool SkTSect::unlinkSpan(SkTSpan* span) { 1520cb93a386Sopenharmony_ci SkTSpan* prev = span->fPrev; 1521cb93a386Sopenharmony_ci SkTSpan* next = span->fNext; 1522cb93a386Sopenharmony_ci if (prev) { 1523cb93a386Sopenharmony_ci prev->fNext = next; 1524cb93a386Sopenharmony_ci if (next) { 1525cb93a386Sopenharmony_ci next->fPrev = prev; 1526cb93a386Sopenharmony_ci if (next->fStartT > next->fEndT) { 1527cb93a386Sopenharmony_ci return false; 1528cb93a386Sopenharmony_ci } 1529cb93a386Sopenharmony_ci // world may not be ready for validate here 1530cb93a386Sopenharmony_ci next->validate(); 1531cb93a386Sopenharmony_ci } 1532cb93a386Sopenharmony_ci } else { 1533cb93a386Sopenharmony_ci fHead = next; 1534cb93a386Sopenharmony_ci if (next) { 1535cb93a386Sopenharmony_ci next->fPrev = nullptr; 1536cb93a386Sopenharmony_ci } 1537cb93a386Sopenharmony_ci } 1538cb93a386Sopenharmony_ci return true; 1539cb93a386Sopenharmony_ci} 1540cb93a386Sopenharmony_ci 1541cb93a386Sopenharmony_cibool SkTSect::updateBounded(SkTSpan* first, 1542cb93a386Sopenharmony_ci SkTSpan* last, SkTSpan* oppFirst) { 1543cb93a386Sopenharmony_ci SkTSpan* test = first; 1544cb93a386Sopenharmony_ci const SkTSpan* final = last->next(); 1545cb93a386Sopenharmony_ci bool deleteSpan = false; 1546cb93a386Sopenharmony_ci do { 1547cb93a386Sopenharmony_ci deleteSpan |= test->removeAllBounded(); 1548cb93a386Sopenharmony_ci } while ((test = test->fNext) != final && test); 1549cb93a386Sopenharmony_ci first->fBounded = nullptr; 1550cb93a386Sopenharmony_ci first->addBounded(oppFirst, &fHeap); 1551cb93a386Sopenharmony_ci // cannot call validate until remove span range is called 1552cb93a386Sopenharmony_ci return deleteSpan; 1553cb93a386Sopenharmony_ci} 1554cb93a386Sopenharmony_ci 1555cb93a386Sopenharmony_civoid SkTSect::validate() const { 1556cb93a386Sopenharmony_ci#if DEBUG_VALIDATE 1557cb93a386Sopenharmony_ci int count = 0; 1558cb93a386Sopenharmony_ci double last = 0; 1559cb93a386Sopenharmony_ci if (fHead) { 1560cb93a386Sopenharmony_ci const SkTSpan* span = fHead; 1561cb93a386Sopenharmony_ci SkASSERT(!span->fPrev); 1562cb93a386Sopenharmony_ci const SkTSpan* next; 1563cb93a386Sopenharmony_ci do { 1564cb93a386Sopenharmony_ci span->validate(); 1565cb93a386Sopenharmony_ci SkASSERT(span->fStartT >= last); 1566cb93a386Sopenharmony_ci last = span->fEndT; 1567cb93a386Sopenharmony_ci ++count; 1568cb93a386Sopenharmony_ci next = span->fNext; 1569cb93a386Sopenharmony_ci SkASSERT(next != span); 1570cb93a386Sopenharmony_ci } while ((span = next) != nullptr); 1571cb93a386Sopenharmony_ci } 1572cb93a386Sopenharmony_ci SkASSERT(count == fActiveCount); 1573cb93a386Sopenharmony_ci#endif 1574cb93a386Sopenharmony_ci#if DEBUG_T_SECT 1575cb93a386Sopenharmony_ci SkASSERT(fActiveCount <= fDebugAllocatedCount); 1576cb93a386Sopenharmony_ci int deletedCount = 0; 1577cb93a386Sopenharmony_ci const SkTSpan* deleted = fDeleted; 1578cb93a386Sopenharmony_ci while (deleted) { 1579cb93a386Sopenharmony_ci ++deletedCount; 1580cb93a386Sopenharmony_ci deleted = deleted->fNext; 1581cb93a386Sopenharmony_ci } 1582cb93a386Sopenharmony_ci const SkTSpan* coincident = fCoincident; 1583cb93a386Sopenharmony_ci while (coincident) { 1584cb93a386Sopenharmony_ci ++deletedCount; 1585cb93a386Sopenharmony_ci coincident = coincident->fNext; 1586cb93a386Sopenharmony_ci } 1587cb93a386Sopenharmony_ci SkASSERT(fActiveCount + deletedCount == fDebugAllocatedCount); 1588cb93a386Sopenharmony_ci#endif 1589cb93a386Sopenharmony_ci} 1590cb93a386Sopenharmony_ci 1591cb93a386Sopenharmony_civoid SkTSect::validateBounded() const { 1592cb93a386Sopenharmony_ci#if DEBUG_VALIDATE 1593cb93a386Sopenharmony_ci if (!fHead) { 1594cb93a386Sopenharmony_ci return; 1595cb93a386Sopenharmony_ci } 1596cb93a386Sopenharmony_ci const SkTSpan* span = fHead; 1597cb93a386Sopenharmony_ci do { 1598cb93a386Sopenharmony_ci span->validateBounded(); 1599cb93a386Sopenharmony_ci } while ((span = span->fNext) != nullptr); 1600cb93a386Sopenharmony_ci#endif 1601cb93a386Sopenharmony_ci} 1602cb93a386Sopenharmony_ci 1603cb93a386Sopenharmony_ciint SkTSect::EndsEqual(const SkTSect* sect1, 1604cb93a386Sopenharmony_ci const SkTSect* sect2, SkIntersections* intersections) { 1605cb93a386Sopenharmony_ci int zeroOneSet = 0; 1606cb93a386Sopenharmony_ci if (sect1->fCurve[0] == sect2->fCurve[0]) { 1607cb93a386Sopenharmony_ci zeroOneSet |= kZeroS1Set | kZeroS2Set; 1608cb93a386Sopenharmony_ci intersections->insert(0, 0, sect1->fCurve[0]); 1609cb93a386Sopenharmony_ci } 1610cb93a386Sopenharmony_ci if (sect1->fCurve[0] == sect2->pointLast()) { 1611cb93a386Sopenharmony_ci zeroOneSet |= kZeroS1Set | kOneS2Set; 1612cb93a386Sopenharmony_ci intersections->insert(0, 1, sect1->fCurve[0]); 1613cb93a386Sopenharmony_ci } 1614cb93a386Sopenharmony_ci if (sect1->pointLast() == sect2->fCurve[0]) { 1615cb93a386Sopenharmony_ci zeroOneSet |= kOneS1Set | kZeroS2Set; 1616cb93a386Sopenharmony_ci intersections->insert(1, 0, sect1->pointLast()); 1617cb93a386Sopenharmony_ci } 1618cb93a386Sopenharmony_ci if (sect1->pointLast() == sect2->pointLast()) { 1619cb93a386Sopenharmony_ci zeroOneSet |= kOneS1Set | kOneS2Set; 1620cb93a386Sopenharmony_ci intersections->insert(1, 1, sect1->pointLast()); 1621cb93a386Sopenharmony_ci } 1622cb93a386Sopenharmony_ci // check for zero 1623cb93a386Sopenharmony_ci if (!(zeroOneSet & (kZeroS1Set | kZeroS2Set)) 1624cb93a386Sopenharmony_ci && sect1->fCurve[0].approximatelyEqual(sect2->fCurve[0])) { 1625cb93a386Sopenharmony_ci zeroOneSet |= kZeroS1Set | kZeroS2Set; 1626cb93a386Sopenharmony_ci intersections->insertNear(0, 0, sect1->fCurve[0], sect2->fCurve[0]); 1627cb93a386Sopenharmony_ci } 1628cb93a386Sopenharmony_ci if (!(zeroOneSet & (kZeroS1Set | kOneS2Set)) 1629cb93a386Sopenharmony_ci && sect1->fCurve[0].approximatelyEqual(sect2->pointLast())) { 1630cb93a386Sopenharmony_ci zeroOneSet |= kZeroS1Set | kOneS2Set; 1631cb93a386Sopenharmony_ci intersections->insertNear(0, 1, sect1->fCurve[0], sect2->pointLast()); 1632cb93a386Sopenharmony_ci } 1633cb93a386Sopenharmony_ci // check for one 1634cb93a386Sopenharmony_ci if (!(zeroOneSet & (kOneS1Set | kZeroS2Set)) 1635cb93a386Sopenharmony_ci && sect1->pointLast().approximatelyEqual(sect2->fCurve[0])) { 1636cb93a386Sopenharmony_ci zeroOneSet |= kOneS1Set | kZeroS2Set; 1637cb93a386Sopenharmony_ci intersections->insertNear(1, 0, sect1->pointLast(), sect2->fCurve[0]); 1638cb93a386Sopenharmony_ci } 1639cb93a386Sopenharmony_ci if (!(zeroOneSet & (kOneS1Set | kOneS2Set)) 1640cb93a386Sopenharmony_ci && sect1->pointLast().approximatelyEqual(sect2->pointLast())) { 1641cb93a386Sopenharmony_ci zeroOneSet |= kOneS1Set | kOneS2Set; 1642cb93a386Sopenharmony_ci intersections->insertNear(1, 1, sect1->pointLast(), sect2->pointLast()); 1643cb93a386Sopenharmony_ci } 1644cb93a386Sopenharmony_ci return zeroOneSet; 1645cb93a386Sopenharmony_ci} 1646cb93a386Sopenharmony_ci 1647cb93a386Sopenharmony_cistruct SkClosestRecord { 1648cb93a386Sopenharmony_ci bool operator<(const SkClosestRecord& rh) const { 1649cb93a386Sopenharmony_ci return fClosest < rh.fClosest; 1650cb93a386Sopenharmony_ci } 1651cb93a386Sopenharmony_ci 1652cb93a386Sopenharmony_ci void addIntersection(SkIntersections* intersections) const { 1653cb93a386Sopenharmony_ci double r1t = fC1Index ? fC1Span->endT() : fC1Span->startT(); 1654cb93a386Sopenharmony_ci double r2t = fC2Index ? fC2Span->endT() : fC2Span->startT(); 1655cb93a386Sopenharmony_ci intersections->insert(r1t, r2t, fC1Span->part()[fC1Index]); 1656cb93a386Sopenharmony_ci } 1657cb93a386Sopenharmony_ci 1658cb93a386Sopenharmony_ci void findEnd(const SkTSpan* span1, const SkTSpan* span2, 1659cb93a386Sopenharmony_ci int c1Index, int c2Index) { 1660cb93a386Sopenharmony_ci const SkTCurve& c1 = span1->part(); 1661cb93a386Sopenharmony_ci const SkTCurve& c2 = span2->part(); 1662cb93a386Sopenharmony_ci if (!c1[c1Index].approximatelyEqual(c2[c2Index])) { 1663cb93a386Sopenharmony_ci return; 1664cb93a386Sopenharmony_ci } 1665cb93a386Sopenharmony_ci double dist = c1[c1Index].distanceSquared(c2[c2Index]); 1666cb93a386Sopenharmony_ci if (fClosest < dist) { 1667cb93a386Sopenharmony_ci return; 1668cb93a386Sopenharmony_ci } 1669cb93a386Sopenharmony_ci fC1Span = span1; 1670cb93a386Sopenharmony_ci fC2Span = span2; 1671cb93a386Sopenharmony_ci fC1StartT = span1->startT(); 1672cb93a386Sopenharmony_ci fC1EndT = span1->endT(); 1673cb93a386Sopenharmony_ci fC2StartT = span2->startT(); 1674cb93a386Sopenharmony_ci fC2EndT = span2->endT(); 1675cb93a386Sopenharmony_ci fC1Index = c1Index; 1676cb93a386Sopenharmony_ci fC2Index = c2Index; 1677cb93a386Sopenharmony_ci fClosest = dist; 1678cb93a386Sopenharmony_ci } 1679cb93a386Sopenharmony_ci 1680cb93a386Sopenharmony_ci bool matesWith(const SkClosestRecord& mate SkDEBUGPARAMS(SkIntersections* i)) const { 1681cb93a386Sopenharmony_ci SkOPOBJASSERT(i, fC1Span == mate.fC1Span || fC1Span->endT() <= mate.fC1Span->startT() 1682cb93a386Sopenharmony_ci || mate.fC1Span->endT() <= fC1Span->startT()); 1683cb93a386Sopenharmony_ci SkOPOBJASSERT(i, fC2Span == mate.fC2Span || fC2Span->endT() <= mate.fC2Span->startT() 1684cb93a386Sopenharmony_ci || mate.fC2Span->endT() <= fC2Span->startT()); 1685cb93a386Sopenharmony_ci return fC1Span == mate.fC1Span || fC1Span->endT() == mate.fC1Span->startT() 1686cb93a386Sopenharmony_ci || fC1Span->startT() == mate.fC1Span->endT() 1687cb93a386Sopenharmony_ci || fC2Span == mate.fC2Span 1688cb93a386Sopenharmony_ci || fC2Span->endT() == mate.fC2Span->startT() 1689cb93a386Sopenharmony_ci || fC2Span->startT() == mate.fC2Span->endT(); 1690cb93a386Sopenharmony_ci } 1691cb93a386Sopenharmony_ci 1692cb93a386Sopenharmony_ci void merge(const SkClosestRecord& mate) { 1693cb93a386Sopenharmony_ci fC1Span = mate.fC1Span; 1694cb93a386Sopenharmony_ci fC2Span = mate.fC2Span; 1695cb93a386Sopenharmony_ci fClosest = mate.fClosest; 1696cb93a386Sopenharmony_ci fC1Index = mate.fC1Index; 1697cb93a386Sopenharmony_ci fC2Index = mate.fC2Index; 1698cb93a386Sopenharmony_ci } 1699cb93a386Sopenharmony_ci 1700cb93a386Sopenharmony_ci void reset() { 1701cb93a386Sopenharmony_ci fClosest = FLT_MAX; 1702cb93a386Sopenharmony_ci SkDEBUGCODE(fC1Span = nullptr); 1703cb93a386Sopenharmony_ci SkDEBUGCODE(fC2Span = nullptr); 1704cb93a386Sopenharmony_ci SkDEBUGCODE(fC1Index = fC2Index = -1); 1705cb93a386Sopenharmony_ci } 1706cb93a386Sopenharmony_ci 1707cb93a386Sopenharmony_ci void update(const SkClosestRecord& mate) { 1708cb93a386Sopenharmony_ci fC1StartT = std::min(fC1StartT, mate.fC1StartT); 1709cb93a386Sopenharmony_ci fC1EndT = std::max(fC1EndT, mate.fC1EndT); 1710cb93a386Sopenharmony_ci fC2StartT = std::min(fC2StartT, mate.fC2StartT); 1711cb93a386Sopenharmony_ci fC2EndT = std::max(fC2EndT, mate.fC2EndT); 1712cb93a386Sopenharmony_ci } 1713cb93a386Sopenharmony_ci 1714cb93a386Sopenharmony_ci const SkTSpan* fC1Span; 1715cb93a386Sopenharmony_ci const SkTSpan* fC2Span; 1716cb93a386Sopenharmony_ci double fC1StartT; 1717cb93a386Sopenharmony_ci double fC1EndT; 1718cb93a386Sopenharmony_ci double fC2StartT; 1719cb93a386Sopenharmony_ci double fC2EndT; 1720cb93a386Sopenharmony_ci double fClosest; 1721cb93a386Sopenharmony_ci int fC1Index; 1722cb93a386Sopenharmony_ci int fC2Index; 1723cb93a386Sopenharmony_ci}; 1724cb93a386Sopenharmony_ci 1725cb93a386Sopenharmony_cistruct SkClosestSect { 1726cb93a386Sopenharmony_ci SkClosestSect() 1727cb93a386Sopenharmony_ci : fUsed(0) { 1728cb93a386Sopenharmony_ci fClosest.push_back().reset(); 1729cb93a386Sopenharmony_ci } 1730cb93a386Sopenharmony_ci 1731cb93a386Sopenharmony_ci bool find(const SkTSpan* span1, const SkTSpan* span2 1732cb93a386Sopenharmony_ci SkDEBUGPARAMS(SkIntersections* i)) { 1733cb93a386Sopenharmony_ci SkClosestRecord* record = &fClosest[fUsed]; 1734cb93a386Sopenharmony_ci record->findEnd(span1, span2, 0, 0); 1735cb93a386Sopenharmony_ci record->findEnd(span1, span2, 0, span2->part().pointLast()); 1736cb93a386Sopenharmony_ci record->findEnd(span1, span2, span1->part().pointLast(), 0); 1737cb93a386Sopenharmony_ci record->findEnd(span1, span2, span1->part().pointLast(), span2->part().pointLast()); 1738cb93a386Sopenharmony_ci if (record->fClosest == FLT_MAX) { 1739cb93a386Sopenharmony_ci return false; 1740cb93a386Sopenharmony_ci } 1741cb93a386Sopenharmony_ci for (int index = 0; index < fUsed; ++index) { 1742cb93a386Sopenharmony_ci SkClosestRecord* test = &fClosest[index]; 1743cb93a386Sopenharmony_ci if (test->matesWith(*record SkDEBUGPARAMS(i))) { 1744cb93a386Sopenharmony_ci if (test->fClosest > record->fClosest) { 1745cb93a386Sopenharmony_ci test->merge(*record); 1746cb93a386Sopenharmony_ci } 1747cb93a386Sopenharmony_ci test->update(*record); 1748cb93a386Sopenharmony_ci record->reset(); 1749cb93a386Sopenharmony_ci return false; 1750cb93a386Sopenharmony_ci } 1751cb93a386Sopenharmony_ci } 1752cb93a386Sopenharmony_ci ++fUsed; 1753cb93a386Sopenharmony_ci fClosest.push_back().reset(); 1754cb93a386Sopenharmony_ci return true; 1755cb93a386Sopenharmony_ci } 1756cb93a386Sopenharmony_ci 1757cb93a386Sopenharmony_ci void finish(SkIntersections* intersections) const { 1758cb93a386Sopenharmony_ci SkSTArray<SkDCubic::kMaxIntersections * 3, 1759cb93a386Sopenharmony_ci const SkClosestRecord*, true> closestPtrs; 1760cb93a386Sopenharmony_ci for (int index = 0; index < fUsed; ++index) { 1761cb93a386Sopenharmony_ci closestPtrs.push_back(&fClosest[index]); 1762cb93a386Sopenharmony_ci } 1763cb93a386Sopenharmony_ci SkTQSort<const SkClosestRecord>(closestPtrs.begin(), closestPtrs.end()); 1764cb93a386Sopenharmony_ci for (int index = 0; index < fUsed; ++index) { 1765cb93a386Sopenharmony_ci const SkClosestRecord* test = closestPtrs[index]; 1766cb93a386Sopenharmony_ci test->addIntersection(intersections); 1767cb93a386Sopenharmony_ci } 1768cb93a386Sopenharmony_ci } 1769cb93a386Sopenharmony_ci 1770cb93a386Sopenharmony_ci // this is oversized so that an extra records can merge into final one 1771cb93a386Sopenharmony_ci SkSTArray<SkDCubic::kMaxIntersections * 2, SkClosestRecord, true> fClosest; 1772cb93a386Sopenharmony_ci int fUsed; 1773cb93a386Sopenharmony_ci}; 1774cb93a386Sopenharmony_ci 1775cb93a386Sopenharmony_ci// returns true if the rect is too small to consider 1776cb93a386Sopenharmony_ci 1777cb93a386Sopenharmony_civoid SkTSect::BinarySearch(SkTSect* sect1, 1778cb93a386Sopenharmony_ci SkTSect* sect2, SkIntersections* intersections) { 1779cb93a386Sopenharmony_ci#if DEBUG_T_SECT_DUMP > 1 1780cb93a386Sopenharmony_ci gDumpTSectNum = 0; 1781cb93a386Sopenharmony_ci#endif 1782cb93a386Sopenharmony_ci SkDEBUGCODE(sect1->fOppSect = sect2); 1783cb93a386Sopenharmony_ci SkDEBUGCODE(sect2->fOppSect = sect1); 1784cb93a386Sopenharmony_ci intersections->reset(); 1785cb93a386Sopenharmony_ci intersections->setMax(sect1->fCurve.maxIntersections() + 4); // give extra for slop 1786cb93a386Sopenharmony_ci SkTSpan* span1 = sect1->fHead; 1787cb93a386Sopenharmony_ci SkTSpan* span2 = sect2->fHead; 1788cb93a386Sopenharmony_ci int oppSect, sect = sect1->intersects(span1, sect2, span2, &oppSect); 1789cb93a386Sopenharmony_ci// SkASSERT(between(0, sect, 2)); 1790cb93a386Sopenharmony_ci if (!sect) { 1791cb93a386Sopenharmony_ci return; 1792cb93a386Sopenharmony_ci } 1793cb93a386Sopenharmony_ci if (sect == 2 && oppSect == 2) { 1794cb93a386Sopenharmony_ci (void) EndsEqual(sect1, sect2, intersections); 1795cb93a386Sopenharmony_ci return; 1796cb93a386Sopenharmony_ci } 1797cb93a386Sopenharmony_ci span1->addBounded(span2, §1->fHeap); 1798cb93a386Sopenharmony_ci span2->addBounded(span1, §2->fHeap); 1799cb93a386Sopenharmony_ci const int kMaxCoinLoopCount = 8; 1800cb93a386Sopenharmony_ci int coinLoopCount = kMaxCoinLoopCount; 1801cb93a386Sopenharmony_ci double start1s SK_INIT_TO_AVOID_WARNING; 1802cb93a386Sopenharmony_ci double start1e SK_INIT_TO_AVOID_WARNING; 1803cb93a386Sopenharmony_ci do { 1804cb93a386Sopenharmony_ci // find the largest bounds 1805cb93a386Sopenharmony_ci SkTSpan* largest1 = sect1->boundsMax(); 1806cb93a386Sopenharmony_ci if (!largest1) { 1807cb93a386Sopenharmony_ci if (sect1->fHung) { 1808cb93a386Sopenharmony_ci return; 1809cb93a386Sopenharmony_ci } 1810cb93a386Sopenharmony_ci break; 1811cb93a386Sopenharmony_ci } 1812cb93a386Sopenharmony_ci SkTSpan* largest2 = sect2->boundsMax(); 1813cb93a386Sopenharmony_ci // split it 1814cb93a386Sopenharmony_ci if (!largest2 || (largest1 && (largest1->fBoundsMax > largest2->fBoundsMax 1815cb93a386Sopenharmony_ci || (!largest1->fCollapsed && largest2->fCollapsed)))) { 1816cb93a386Sopenharmony_ci if (sect2->fHung) { 1817cb93a386Sopenharmony_ci return; 1818cb93a386Sopenharmony_ci } 1819cb93a386Sopenharmony_ci if (largest1->fCollapsed) { 1820cb93a386Sopenharmony_ci break; 1821cb93a386Sopenharmony_ci } 1822cb93a386Sopenharmony_ci sect1->resetRemovedEnds(); 1823cb93a386Sopenharmony_ci sect2->resetRemovedEnds(); 1824cb93a386Sopenharmony_ci // trim parts that don't intersect the opposite 1825cb93a386Sopenharmony_ci SkTSpan* half1 = sect1->addOne(); 1826cb93a386Sopenharmony_ci SkDEBUGCODE(half1->debugSetGlobalState(sect1->globalState())); 1827cb93a386Sopenharmony_ci if (!half1->split(largest1, §1->fHeap)) { 1828cb93a386Sopenharmony_ci break; 1829cb93a386Sopenharmony_ci } 1830cb93a386Sopenharmony_ci if (!sect1->trim(largest1, sect2)) { 1831cb93a386Sopenharmony_ci SkOPOBJASSERT(intersections, 0); 1832cb93a386Sopenharmony_ci return; 1833cb93a386Sopenharmony_ci } 1834cb93a386Sopenharmony_ci if (!sect1->trim(half1, sect2)) { 1835cb93a386Sopenharmony_ci SkOPOBJASSERT(intersections, 0); 1836cb93a386Sopenharmony_ci return; 1837cb93a386Sopenharmony_ci } 1838cb93a386Sopenharmony_ci } else { 1839cb93a386Sopenharmony_ci if (largest2->fCollapsed) { 1840cb93a386Sopenharmony_ci break; 1841cb93a386Sopenharmony_ci } 1842cb93a386Sopenharmony_ci sect1->resetRemovedEnds(); 1843cb93a386Sopenharmony_ci sect2->resetRemovedEnds(); 1844cb93a386Sopenharmony_ci // trim parts that don't intersect the opposite 1845cb93a386Sopenharmony_ci SkTSpan* half2 = sect2->addOne(); 1846cb93a386Sopenharmony_ci SkDEBUGCODE(half2->debugSetGlobalState(sect2->globalState())); 1847cb93a386Sopenharmony_ci if (!half2->split(largest2, §2->fHeap)) { 1848cb93a386Sopenharmony_ci break; 1849cb93a386Sopenharmony_ci } 1850cb93a386Sopenharmony_ci if (!sect2->trim(largest2, sect1)) { 1851cb93a386Sopenharmony_ci SkOPOBJASSERT(intersections, 0); 1852cb93a386Sopenharmony_ci return; 1853cb93a386Sopenharmony_ci } 1854cb93a386Sopenharmony_ci if (!sect2->trim(half2, sect1)) { 1855cb93a386Sopenharmony_ci SkOPOBJASSERT(intersections, 0); 1856cb93a386Sopenharmony_ci return; 1857cb93a386Sopenharmony_ci } 1858cb93a386Sopenharmony_ci } 1859cb93a386Sopenharmony_ci sect1->validate(); 1860cb93a386Sopenharmony_ci sect2->validate(); 1861cb93a386Sopenharmony_ci#if DEBUG_T_SECT_LOOP_COUNT 1862cb93a386Sopenharmony_ci intersections->debugBumpLoopCount(SkIntersections::kIterations_DebugLoop); 1863cb93a386Sopenharmony_ci#endif 1864cb93a386Sopenharmony_ci // if there are 9 or more continuous spans on both sects, suspect coincidence 1865cb93a386Sopenharmony_ci if (sect1->fActiveCount >= COINCIDENT_SPAN_COUNT 1866cb93a386Sopenharmony_ci && sect2->fActiveCount >= COINCIDENT_SPAN_COUNT) { 1867cb93a386Sopenharmony_ci if (coinLoopCount == kMaxCoinLoopCount) { 1868cb93a386Sopenharmony_ci start1s = sect1->fHead->fStartT; 1869cb93a386Sopenharmony_ci start1e = sect1->tail()->fEndT; 1870cb93a386Sopenharmony_ci } 1871cb93a386Sopenharmony_ci if (!sect1->coincidentCheck(sect2)) { 1872cb93a386Sopenharmony_ci return; 1873cb93a386Sopenharmony_ci } 1874cb93a386Sopenharmony_ci sect1->validate(); 1875cb93a386Sopenharmony_ci sect2->validate(); 1876cb93a386Sopenharmony_ci#if DEBUG_T_SECT_LOOP_COUNT 1877cb93a386Sopenharmony_ci intersections->debugBumpLoopCount(SkIntersections::kCoinCheck_DebugLoop); 1878cb93a386Sopenharmony_ci#endif 1879cb93a386Sopenharmony_ci if (!--coinLoopCount && sect1->fHead && sect2->fHead) { 1880cb93a386Sopenharmony_ci /* All known working cases resolve in two tries. Sadly, cubicConicTests[0] 1881cb93a386Sopenharmony_ci gets stuck in a loop. It adds an extension to allow a coincident end 1882cb93a386Sopenharmony_ci perpendicular to track its intersection in the opposite curve. However, 1883cb93a386Sopenharmony_ci the bounding box of the extension does not intersect the original curve, 1884cb93a386Sopenharmony_ci so the extension is discarded, only to be added again the next time around. */ 1885cb93a386Sopenharmony_ci sect1->coincidentForce(sect2, start1s, start1e); 1886cb93a386Sopenharmony_ci sect1->validate(); 1887cb93a386Sopenharmony_ci sect2->validate(); 1888cb93a386Sopenharmony_ci } 1889cb93a386Sopenharmony_ci } 1890cb93a386Sopenharmony_ci if (sect1->fActiveCount >= COINCIDENT_SPAN_COUNT 1891cb93a386Sopenharmony_ci && sect2->fActiveCount >= COINCIDENT_SPAN_COUNT) { 1892cb93a386Sopenharmony_ci if (!sect1->fHead) { 1893cb93a386Sopenharmony_ci return; 1894cb93a386Sopenharmony_ci } 1895cb93a386Sopenharmony_ci sect1->computePerpendiculars(sect2, sect1->fHead, sect1->tail()); 1896cb93a386Sopenharmony_ci if (!sect2->fHead) { 1897cb93a386Sopenharmony_ci return; 1898cb93a386Sopenharmony_ci } 1899cb93a386Sopenharmony_ci sect2->computePerpendiculars(sect1, sect2->fHead, sect2->tail()); 1900cb93a386Sopenharmony_ci if (!sect1->removeByPerpendicular(sect2)) { 1901cb93a386Sopenharmony_ci return; 1902cb93a386Sopenharmony_ci } 1903cb93a386Sopenharmony_ci sect1->validate(); 1904cb93a386Sopenharmony_ci sect2->validate(); 1905cb93a386Sopenharmony_ci#if DEBUG_T_SECT_LOOP_COUNT 1906cb93a386Sopenharmony_ci intersections->debugBumpLoopCount(SkIntersections::kComputePerp_DebugLoop); 1907cb93a386Sopenharmony_ci#endif 1908cb93a386Sopenharmony_ci if (sect1->collapsed() > sect1->fCurve.maxIntersections()) { 1909cb93a386Sopenharmony_ci break; 1910cb93a386Sopenharmony_ci } 1911cb93a386Sopenharmony_ci } 1912cb93a386Sopenharmony_ci#if DEBUG_T_SECT_DUMP 1913cb93a386Sopenharmony_ci sect1->dumpBoth(sect2); 1914cb93a386Sopenharmony_ci#endif 1915cb93a386Sopenharmony_ci if (!sect1->fHead || !sect2->fHead) { 1916cb93a386Sopenharmony_ci break; 1917cb93a386Sopenharmony_ci } 1918cb93a386Sopenharmony_ci } while (true); 1919cb93a386Sopenharmony_ci SkTSpan* coincident = sect1->fCoincident; 1920cb93a386Sopenharmony_ci if (coincident) { 1921cb93a386Sopenharmony_ci // if there is more than one coincident span, check loosely to see if they should be joined 1922cb93a386Sopenharmony_ci if (coincident->fNext) { 1923cb93a386Sopenharmony_ci sect1->mergeCoincidence(sect2); 1924cb93a386Sopenharmony_ci coincident = sect1->fCoincident; 1925cb93a386Sopenharmony_ci } 1926cb93a386Sopenharmony_ci SkASSERT(sect2->fCoincident); // courtesy check : coincidence only looks at sect 1 1927cb93a386Sopenharmony_ci do { 1928cb93a386Sopenharmony_ci if (!coincident) { 1929cb93a386Sopenharmony_ci return; 1930cb93a386Sopenharmony_ci } 1931cb93a386Sopenharmony_ci if (!coincident->fCoinStart.isMatch()) { 1932cb93a386Sopenharmony_ci continue; 1933cb93a386Sopenharmony_ci } 1934cb93a386Sopenharmony_ci if (!coincident->fCoinEnd.isMatch()) { 1935cb93a386Sopenharmony_ci continue; 1936cb93a386Sopenharmony_ci } 1937cb93a386Sopenharmony_ci double perpT = coincident->fCoinStart.perpT(); 1938cb93a386Sopenharmony_ci if (perpT < 0) { 1939cb93a386Sopenharmony_ci return; 1940cb93a386Sopenharmony_ci } 1941cb93a386Sopenharmony_ci int index = intersections->insertCoincident(coincident->fStartT, 1942cb93a386Sopenharmony_ci perpT, coincident->pointFirst()); 1943cb93a386Sopenharmony_ci if ((intersections->insertCoincident(coincident->fEndT, 1944cb93a386Sopenharmony_ci coincident->fCoinEnd.perpT(), 1945cb93a386Sopenharmony_ci coincident->pointLast()) < 0) && index >= 0) { 1946cb93a386Sopenharmony_ci intersections->clearCoincidence(index); 1947cb93a386Sopenharmony_ci } 1948cb93a386Sopenharmony_ci } while ((coincident = coincident->fNext)); 1949cb93a386Sopenharmony_ci } 1950cb93a386Sopenharmony_ci int zeroOneSet = EndsEqual(sect1, sect2, intersections); 1951cb93a386Sopenharmony_ci// if (!sect1->fHead || !sect2->fHead) { 1952cb93a386Sopenharmony_ci // if the final iteration contains an end (0 or 1), 1953cb93a386Sopenharmony_ci if (sect1->fRemovedStartT && !(zeroOneSet & kZeroS1Set)) { 1954cb93a386Sopenharmony_ci SkTCoincident perp; // intersect perpendicular with opposite curve 1955cb93a386Sopenharmony_ci perp.setPerp(sect1->fCurve, 0, sect1->fCurve[0], sect2->fCurve); 1956cb93a386Sopenharmony_ci if (perp.isMatch()) { 1957cb93a386Sopenharmony_ci intersections->insert(0, perp.perpT(), perp.perpPt()); 1958cb93a386Sopenharmony_ci } 1959cb93a386Sopenharmony_ci } 1960cb93a386Sopenharmony_ci if (sect1->fRemovedEndT && !(zeroOneSet & kOneS1Set)) { 1961cb93a386Sopenharmony_ci SkTCoincident perp; 1962cb93a386Sopenharmony_ci perp.setPerp(sect1->fCurve, 1, sect1->pointLast(), sect2->fCurve); 1963cb93a386Sopenharmony_ci if (perp.isMatch()) { 1964cb93a386Sopenharmony_ci intersections->insert(1, perp.perpT(), perp.perpPt()); 1965cb93a386Sopenharmony_ci } 1966cb93a386Sopenharmony_ci } 1967cb93a386Sopenharmony_ci if (sect2->fRemovedStartT && !(zeroOneSet & kZeroS2Set)) { 1968cb93a386Sopenharmony_ci SkTCoincident perp; 1969cb93a386Sopenharmony_ci perp.setPerp(sect2->fCurve, 0, sect2->fCurve[0], sect1->fCurve); 1970cb93a386Sopenharmony_ci if (perp.isMatch()) { 1971cb93a386Sopenharmony_ci intersections->insert(perp.perpT(), 0, perp.perpPt()); 1972cb93a386Sopenharmony_ci } 1973cb93a386Sopenharmony_ci } 1974cb93a386Sopenharmony_ci if (sect2->fRemovedEndT && !(zeroOneSet & kOneS2Set)) { 1975cb93a386Sopenharmony_ci SkTCoincident perp; 1976cb93a386Sopenharmony_ci perp.setPerp(sect2->fCurve, 1, sect2->pointLast(), sect1->fCurve); 1977cb93a386Sopenharmony_ci if (perp.isMatch()) { 1978cb93a386Sopenharmony_ci intersections->insert(perp.perpT(), 1, perp.perpPt()); 1979cb93a386Sopenharmony_ci } 1980cb93a386Sopenharmony_ci } 1981cb93a386Sopenharmony_ci// } 1982cb93a386Sopenharmony_ci if (!sect1->fHead || !sect2->fHead) { 1983cb93a386Sopenharmony_ci return; 1984cb93a386Sopenharmony_ci } 1985cb93a386Sopenharmony_ci sect1->recoverCollapsed(); 1986cb93a386Sopenharmony_ci sect2->recoverCollapsed(); 1987cb93a386Sopenharmony_ci SkTSpan* result1 = sect1->fHead; 1988cb93a386Sopenharmony_ci // check heads and tails for zero and ones and insert them if we haven't already done so 1989cb93a386Sopenharmony_ci const SkTSpan* head1 = result1; 1990cb93a386Sopenharmony_ci if (!(zeroOneSet & kZeroS1Set) && approximately_less_than_zero(head1->fStartT)) { 1991cb93a386Sopenharmony_ci const SkDPoint& start1 = sect1->fCurve[0]; 1992cb93a386Sopenharmony_ci if (head1->isBounded()) { 1993cb93a386Sopenharmony_ci double t = head1->closestBoundedT(start1); 1994cb93a386Sopenharmony_ci if (sect2->fCurve.ptAtT(t).approximatelyEqual(start1)) { 1995cb93a386Sopenharmony_ci intersections->insert(0, t, start1); 1996cb93a386Sopenharmony_ci } 1997cb93a386Sopenharmony_ci } 1998cb93a386Sopenharmony_ci } 1999cb93a386Sopenharmony_ci const SkTSpan* head2 = sect2->fHead; 2000cb93a386Sopenharmony_ci if (!(zeroOneSet & kZeroS2Set) && approximately_less_than_zero(head2->fStartT)) { 2001cb93a386Sopenharmony_ci const SkDPoint& start2 = sect2->fCurve[0]; 2002cb93a386Sopenharmony_ci if (head2->isBounded()) { 2003cb93a386Sopenharmony_ci double t = head2->closestBoundedT(start2); 2004cb93a386Sopenharmony_ci if (sect1->fCurve.ptAtT(t).approximatelyEqual(start2)) { 2005cb93a386Sopenharmony_ci intersections->insert(t, 0, start2); 2006cb93a386Sopenharmony_ci } 2007cb93a386Sopenharmony_ci } 2008cb93a386Sopenharmony_ci } 2009cb93a386Sopenharmony_ci if (!(zeroOneSet & kOneS1Set)) { 2010cb93a386Sopenharmony_ci const SkTSpan* tail1 = sect1->tail(); 2011cb93a386Sopenharmony_ci if (!tail1) { 2012cb93a386Sopenharmony_ci return; 2013cb93a386Sopenharmony_ci } 2014cb93a386Sopenharmony_ci if (approximately_greater_than_one(tail1->fEndT)) { 2015cb93a386Sopenharmony_ci const SkDPoint& end1 = sect1->pointLast(); 2016cb93a386Sopenharmony_ci if (tail1->isBounded()) { 2017cb93a386Sopenharmony_ci double t = tail1->closestBoundedT(end1); 2018cb93a386Sopenharmony_ci if (sect2->fCurve.ptAtT(t).approximatelyEqual(end1)) { 2019cb93a386Sopenharmony_ci intersections->insert(1, t, end1); 2020cb93a386Sopenharmony_ci } 2021cb93a386Sopenharmony_ci } 2022cb93a386Sopenharmony_ci } 2023cb93a386Sopenharmony_ci } 2024cb93a386Sopenharmony_ci if (!(zeroOneSet & kOneS2Set)) { 2025cb93a386Sopenharmony_ci const SkTSpan* tail2 = sect2->tail(); 2026cb93a386Sopenharmony_ci if (!tail2) { 2027cb93a386Sopenharmony_ci return; 2028cb93a386Sopenharmony_ci } 2029cb93a386Sopenharmony_ci if (approximately_greater_than_one(tail2->fEndT)) { 2030cb93a386Sopenharmony_ci const SkDPoint& end2 = sect2->pointLast(); 2031cb93a386Sopenharmony_ci if (tail2->isBounded()) { 2032cb93a386Sopenharmony_ci double t = tail2->closestBoundedT(end2); 2033cb93a386Sopenharmony_ci if (sect1->fCurve.ptAtT(t).approximatelyEqual(end2)) { 2034cb93a386Sopenharmony_ci intersections->insert(t, 1, end2); 2035cb93a386Sopenharmony_ci } 2036cb93a386Sopenharmony_ci } 2037cb93a386Sopenharmony_ci } 2038cb93a386Sopenharmony_ci } 2039cb93a386Sopenharmony_ci SkClosestSect closest; 2040cb93a386Sopenharmony_ci do { 2041cb93a386Sopenharmony_ci while (result1 && result1->fCoinStart.isMatch() && result1->fCoinEnd.isMatch()) { 2042cb93a386Sopenharmony_ci result1 = result1->fNext; 2043cb93a386Sopenharmony_ci } 2044cb93a386Sopenharmony_ci if (!result1) { 2045cb93a386Sopenharmony_ci break; 2046cb93a386Sopenharmony_ci } 2047cb93a386Sopenharmony_ci SkTSpan* result2 = sect2->fHead; 2048cb93a386Sopenharmony_ci while (result2) { 2049cb93a386Sopenharmony_ci closest.find(result1, result2 SkDEBUGPARAMS(intersections)); 2050cb93a386Sopenharmony_ci result2 = result2->fNext; 2051cb93a386Sopenharmony_ci } 2052cb93a386Sopenharmony_ci } while ((result1 = result1->fNext)); 2053cb93a386Sopenharmony_ci closest.finish(intersections); 2054cb93a386Sopenharmony_ci // if there is more than one intersection and it isn't already coincident, check 2055cb93a386Sopenharmony_ci int last = intersections->used() - 1; 2056cb93a386Sopenharmony_ci for (int index = 0; index < last; ) { 2057cb93a386Sopenharmony_ci if (intersections->isCoincident(index) && intersections->isCoincident(index + 1)) { 2058cb93a386Sopenharmony_ci ++index; 2059cb93a386Sopenharmony_ci continue; 2060cb93a386Sopenharmony_ci } 2061cb93a386Sopenharmony_ci double midT = ((*intersections)[0][index] + (*intersections)[0][index + 1]) / 2; 2062cb93a386Sopenharmony_ci SkDPoint midPt = sect1->fCurve.ptAtT(midT); 2063cb93a386Sopenharmony_ci // intersect perpendicular with opposite curve 2064cb93a386Sopenharmony_ci SkTCoincident perp; 2065cb93a386Sopenharmony_ci perp.setPerp(sect1->fCurve, midT, midPt, sect2->fCurve); 2066cb93a386Sopenharmony_ci if (!perp.isMatch()) { 2067cb93a386Sopenharmony_ci ++index; 2068cb93a386Sopenharmony_ci continue; 2069cb93a386Sopenharmony_ci } 2070cb93a386Sopenharmony_ci if (intersections->isCoincident(index)) { 2071cb93a386Sopenharmony_ci intersections->removeOne(index); 2072cb93a386Sopenharmony_ci --last; 2073cb93a386Sopenharmony_ci } else if (intersections->isCoincident(index + 1)) { 2074cb93a386Sopenharmony_ci intersections->removeOne(index + 1); 2075cb93a386Sopenharmony_ci --last; 2076cb93a386Sopenharmony_ci } else { 2077cb93a386Sopenharmony_ci intersections->setCoincident(index++); 2078cb93a386Sopenharmony_ci } 2079cb93a386Sopenharmony_ci intersections->setCoincident(index); 2080cb93a386Sopenharmony_ci } 2081cb93a386Sopenharmony_ci SkOPOBJASSERT(intersections, intersections->used() <= sect1->fCurve.maxIntersections()); 2082cb93a386Sopenharmony_ci} 2083cb93a386Sopenharmony_ci 2084cb93a386Sopenharmony_ciint SkIntersections::intersect(const SkDQuad& q1, const SkDQuad& q2) { 2085cb93a386Sopenharmony_ci SkTQuad quad1(q1); 2086cb93a386Sopenharmony_ci SkTQuad quad2(q2); 2087cb93a386Sopenharmony_ci SkTSect sect1(quad1 SkDEBUGPARAMS(globalState()) PATH_OPS_DEBUG_T_SECT_PARAMS(1)); 2088cb93a386Sopenharmony_ci SkTSect sect2(quad2 SkDEBUGPARAMS(globalState()) PATH_OPS_DEBUG_T_SECT_PARAMS(2)); 2089cb93a386Sopenharmony_ci SkTSect::BinarySearch(§1, §2, this); 2090cb93a386Sopenharmony_ci return used(); 2091cb93a386Sopenharmony_ci} 2092cb93a386Sopenharmony_ci 2093cb93a386Sopenharmony_ciint SkIntersections::intersect(const SkDConic& c, const SkDQuad& q) { 2094cb93a386Sopenharmony_ci SkTConic conic(c); 2095cb93a386Sopenharmony_ci SkTQuad quad(q); 2096cb93a386Sopenharmony_ci SkTSect sect1(conic SkDEBUGPARAMS(globalState()) PATH_OPS_DEBUG_T_SECT_PARAMS(1)); 2097cb93a386Sopenharmony_ci SkTSect sect2(quad SkDEBUGPARAMS(globalState()) PATH_OPS_DEBUG_T_SECT_PARAMS(2)); 2098cb93a386Sopenharmony_ci SkTSect::BinarySearch(§1, §2, this); 2099cb93a386Sopenharmony_ci return used(); 2100cb93a386Sopenharmony_ci} 2101cb93a386Sopenharmony_ci 2102cb93a386Sopenharmony_ciint SkIntersections::intersect(const SkDConic& c1, const SkDConic& c2) { 2103cb93a386Sopenharmony_ci SkTConic conic1(c1); 2104cb93a386Sopenharmony_ci SkTConic conic2(c2); 2105cb93a386Sopenharmony_ci SkTSect sect1(conic1 SkDEBUGPARAMS(globalState()) PATH_OPS_DEBUG_T_SECT_PARAMS(1)); 2106cb93a386Sopenharmony_ci SkTSect sect2(conic2 SkDEBUGPARAMS(globalState()) PATH_OPS_DEBUG_T_SECT_PARAMS(2)); 2107cb93a386Sopenharmony_ci SkTSect::BinarySearch(§1, §2, this); 2108cb93a386Sopenharmony_ci return used(); 2109cb93a386Sopenharmony_ci} 2110cb93a386Sopenharmony_ci 2111cb93a386Sopenharmony_ciint SkIntersections::intersect(const SkDCubic& c, const SkDQuad& q) { 2112cb93a386Sopenharmony_ci SkTCubic cubic(c); 2113cb93a386Sopenharmony_ci SkTQuad quad(q); 2114cb93a386Sopenharmony_ci SkTSect sect1(cubic SkDEBUGPARAMS(globalState()) PATH_OPS_DEBUG_T_SECT_PARAMS(1)); 2115cb93a386Sopenharmony_ci SkTSect sect2(quad SkDEBUGPARAMS(globalState()) PATH_OPS_DEBUG_T_SECT_PARAMS(2)); 2116cb93a386Sopenharmony_ci SkTSect::BinarySearch(§1, §2, this); 2117cb93a386Sopenharmony_ci return used(); 2118cb93a386Sopenharmony_ci} 2119cb93a386Sopenharmony_ci 2120cb93a386Sopenharmony_ciint SkIntersections::intersect(const SkDCubic& cu, const SkDConic& co) { 2121cb93a386Sopenharmony_ci SkTCubic cubic(cu); 2122cb93a386Sopenharmony_ci SkTConic conic(co); 2123cb93a386Sopenharmony_ci SkTSect sect1(cubic SkDEBUGPARAMS(globalState()) PATH_OPS_DEBUG_T_SECT_PARAMS(1)); 2124cb93a386Sopenharmony_ci SkTSect sect2(conic SkDEBUGPARAMS(globalState()) PATH_OPS_DEBUG_T_SECT_PARAMS(2)); 2125cb93a386Sopenharmony_ci SkTSect::BinarySearch(§1, §2, this); 2126cb93a386Sopenharmony_ci return used(); 2127cb93a386Sopenharmony_ci 2128cb93a386Sopenharmony_ci} 2129cb93a386Sopenharmony_ci 2130cb93a386Sopenharmony_ciint SkIntersections::intersect(const SkDCubic& c1, const SkDCubic& c2) { 2131cb93a386Sopenharmony_ci SkTCubic cubic1(c1); 2132cb93a386Sopenharmony_ci SkTCubic cubic2(c2); 2133cb93a386Sopenharmony_ci SkTSect sect1(cubic1 SkDEBUGPARAMS(globalState()) PATH_OPS_DEBUG_T_SECT_PARAMS(1)); 2134cb93a386Sopenharmony_ci SkTSect sect2(cubic2 SkDEBUGPARAMS(globalState()) PATH_OPS_DEBUG_T_SECT_PARAMS(2)); 2135cb93a386Sopenharmony_ci SkTSect::BinarySearch(§1, §2, this); 2136cb93a386Sopenharmony_ci return used(); 2137cb93a386Sopenharmony_ci} 2138