1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* 2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2014 Google Inc. 3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be 5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file. 6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkOpCoincidence.h" 8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkOpContour.h" 9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkOpSegment.h" 10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPathWriter.h" 11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpPtT::alias() const { 13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return this->span()->ptT() != this; 14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkOpPtT* SkOpPtT::active() const { 17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!fDeleted) { 18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return this; 19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ptT = this; 21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* stopPtT = ptT; 22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((ptT = ptT->next()) != stopPtT) { 23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (ptT->fSpan == fSpan && !ptT->fDeleted) { 24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return ptT; 25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(0); // should never return deleted 28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return this; 29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpPtT::contains(const SkOpPtT* check) const { 32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(this != check); 33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ptT = this; 34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* stopPtT = ptT; 35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((ptT = ptT->next()) != stopPtT) { 36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (ptT == check) { 37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpPtT::contains(const SkOpSegment* segment, const SkPoint& pt) const { 44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(this->segment() != segment); 45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ptT = this; 46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* stopPtT = ptT; 47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((ptT = ptT->next()) != stopPtT) { 48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (ptT->fPt == pt && ptT->segment() == segment) { 49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpPtT::contains(const SkOpSegment* segment, double t) const { 56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ptT = this; 57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* stopPtT = ptT; 58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((ptT = ptT->next()) != stopPtT) { 59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (ptT->fT == t && ptT->segment() == segment) { 60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkOpPtT* SkOpPtT::contains(const SkOpSegment* check) const { 67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(this->segment() != check); 68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ptT = this; 69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* stopPtT = ptT; 70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((ptT = ptT->next()) != stopPtT) { 71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (ptT->segment() == check && !ptT->deleted()) { 72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return ptT; 73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkOpContour* SkOpPtT::contour() const { 79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return segment()->contour(); 80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkOpPtT* SkOpPtT::find(const SkOpSegment* segment) const { 83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ptT = this; 84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* stopPtT = ptT; 85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (ptT->segment() == segment && !ptT->deleted()) { 87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return ptT; 88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ptT = ptT->fNext; 90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (stopPtT != ptT); 91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkASSERT(0); 92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkOpGlobalState* SkOpPtT::globalState() const { 96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return contour()->globalState(); 97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpPtT::init(SkOpSpanBase* span, double t, const SkPoint& pt, bool duplicate) { 100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fT = t; 101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fPt = pt; 102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fSpan = span; 103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fNext = this; 104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDuplicatePt = duplicate; 105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDeleted = false; 106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCoincident = false; 107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(fID = span->globalState()->nextPtTID()); 108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpPtT::onEnd() const { 111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* span = this->span(); 112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (span->ptT() != this) { 113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* segment = this->segment(); 116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return span == segment->head() || span == segment->tail(); 117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpPtT::ptAlreadySeen(const SkOpPtT* check) const { 120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (this != check) { 121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->fPt == check->fPt) { 122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check = check->fNext; 125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkOpPtT* SkOpPtT::prev() { 130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* result = this; 131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* next = this; 132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((next = next->fNext) != this) { 133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result = next; 134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(result->fNext == this); 136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return result; 137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkOpSegment* SkOpPtT::segment() const { 140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return span()->segment(); 141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkOpSegment* SkOpPtT::segment() { 144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return span()->segment(); 145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpPtT::setDeleted() { 148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(this->span()->debugDeleted() || this->span()->ptT() != this); 149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(!fDeleted); 150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDeleted = true; 151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSpanBase::addOpp(SkOpSpanBase* opp) { 154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* oppPrev = this->ptT()->oppPrev(opp->ptT()); 155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!oppPrev) { 156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->mergeMatches(opp); 159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->ptT()->addOpp(opp->ptT(), oppPrev); 160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->checkForCollapsedCoincidence(); 161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpSpanBase::collapsed(double s, double e) const { 164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* start = &fPtT; 165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* walk = start; 166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double min = walk->fT; 167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double max = min; 168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* segment = this->segment(); 169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((walk = walk->next()) != start) { 170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (walk->segment() != segment) { 171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot min = SkTMin(min, walk->fT); 174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot max = SkTMax(max, walk->fT); 175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (between(min, s, max) && between(min, e, max)) { 176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpSpanBase::contains(const SkOpSpanBase* span) const { 183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* start = &fPtT; 184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* check = &span->fPtT; 185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(start != check); 186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* walk = start; 187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((walk = walk->next()) != start) { 188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (walk == check) { 189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkOpPtT* SkOpSpanBase::contains(const SkOpSegment* segment) const { 196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* start = &fPtT; 197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* walk = start; 198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((walk = walk->next()) != start) { 199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (walk->deleted()) { 200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (walk->segment() == segment && walk->span()->ptT() == walk) { 203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return walk; 204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpSpanBase::containsCoinEnd(const SkOpSegment* segment) const { 210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(this->segment() != segment); 211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* next = this; 212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((next = next->fCoinEnd) != this) { 213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (next->segment() == segment) { 214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkOpContour* SkOpSpanBase::contour() const { 221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return segment()->contour(); 222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkOpGlobalState* SkOpSpanBase::globalState() const { 225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return contour()->globalState(); 226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSpanBase::initBase(SkOpSegment* segment, SkOpSpan* prev, double t, const SkPoint& pt) { 229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fSegment = segment; 230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fPtT.init(this, t, pt, false); 231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCoinEnd = this; 232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFromAngle = nullptr; 233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fPrev = prev; 234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fSpanAdds = 0; 235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fAligned = true; 236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fChased = false; 237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(fCount = 1); 238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(fID = globalState()->nextSpanID()); 239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(fDebugDeleted = false); 240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// this pair of spans share a common t value or point; merge them and eliminate duplicates 243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// this does not compute the best t or pt value; this merely moves all data into a single list 244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSpanBase::merge(SkOpSpan* span) { 245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* spanPtT = span->ptT(); 246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(this->t() != spanPtT->fT); 247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!zero_or_one(spanPtT->fT)); 248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot span->release(this->ptT()); 249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->contains(span)) { 250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(0); // check to see if this ever happens -- should have been found earlier 251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; // merge is already in the ptT loop 252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* remainder = spanPtT->next(); 254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->ptT()->insert(spanPtT); 255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (remainder != spanPtT) { 256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* next = remainder->next(); 257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* compare = spanPtT->next(); 258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (compare != spanPtT) { 259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* nextC = compare->next(); 260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (nextC->span() == remainder->span() && nextC->fT == remainder->fT) { 261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot goto tryNextRemainder; 262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot compare = nextC; 264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot spanPtT->insert(remainder); 266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobottryNextRemainder: 267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot remainder = next; 268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fSpanAdds += span->fSpanAdds; 270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkOpSpanBase* SkOpSpanBase::active() { 273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* result = fPrev ? fPrev->next() : upCast()->next()->prev(); 274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(this == result || fDebugDeleted); 275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return result; 276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// please keep in sync with debugCheckForCollapsedCoincidence() 279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSpanBase::checkForCollapsedCoincidence() { 280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpCoincidence* coins = this->globalState()->coincidence(); 281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coins->isEmpty()) { 282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// the insert above may have put both ends of a coincident run in the same span 285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// for each coincident ptT in loop; see if its opposite in is also in the loop 286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// this implementation is the motivation for marking that a ptT is referenced by a coincident span 287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* head = this->ptT(); 288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* test = head; 289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!test->coincident()) { 291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coins->markCollapsed(test); 294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((test = test->next()) != head); 295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coins->releaseDeleted(); 296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// please keep in sync with debugMergeMatches() 299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Look to see if pt-t linked list contains same segment more than once 300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// if so, and if each pt-t is directly pointed to by spans in that segment, 301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// merge them 302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// keep the points, but remove spans so that the segment doesn't have 2 or more 303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// spans pointing to the same pt-t loop at different loop elements 304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSpanBase::mergeMatches(SkOpSpanBase* opp) { 305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* test = &fPtT; 306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* testNext; 307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* stop = test; 308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot testNext = test->next(); 310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (test->deleted()) { 311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* testBase = test->span(); 314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(testBase->ptT() == test); 315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSegment* segment = test->segment(); 316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (segment->done()) { 317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* inner = opp->ptT(); 320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* innerStop = inner; 321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (inner->segment() != segment) { 323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (inner->deleted()) { 326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* innerBase = inner->span(); 329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(innerBase->ptT() == inner); 330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // when the intersection is first detected, the span base is marked if there are 331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // more than one point in the intersection. 332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!zero_or_one(inner->fT)) { 333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot innerBase->upCast()->release(test); 334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(inner->fT != test->fT); 336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!zero_or_one(test->fT)) { 337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot testBase->upCast()->release(inner); 338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot segment->markAllDone(); // mark segment as collapsed 340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(testBase->debugSetDeleted()); 341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test->setDeleted(); 342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(innerBase->debugSetDeleted()); 343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot inner->setDeleted(); 344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_DEBUG // assert if another undeleted entry points to segment 347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* debugInner = inner; 348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((debugInner = debugInner->next()) != innerStop) { 349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (debugInner->segment() != segment) { 350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (debugInner->deleted()) { 353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(0); 356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((inner = inner->next()) != innerStop); 360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((test = testNext) != stop); 361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->checkForCollapsedCoincidence(); 362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotint SkOpSpan::computeWindSum() { 365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpGlobalState* globals = this->globalState(); 366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpContour* contourHead = globals->contourHead(); 367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int windTry = 0; 368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (!this->sortableTop(contourHead) && ++windTry < SkOpGlobalState::kMaxWindingTries) { 369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ; 370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return this->windSum(); 372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpSpan::containsCoincidence(const SkOpSegment* segment) const { 375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(this->segment() != segment); 376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* next = fCoincident; 377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (next->segment() == segment) { 379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((next = next->fCoincident) != this); 382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSpan::init(SkOpSegment* segment, SkOpSpan* prev, double t, const SkPoint& pt) { 386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(t != 1); 387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot initBase(segment, prev, t, pt); 388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCoincident = this; 389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fToAngle = nullptr; 390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fWindSum = fOppSum = SK_MinS32; 391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fWindValue = 1; 392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fOppValue = 0; 393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fTopTTry = 0; 394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fChased = fDone = false; 395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot segment->bumpCount(); 396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fAlreadyAdded = false; 397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Please keep this in sync with debugInsertCoincidence() 400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpSpan::insertCoincidence(const SkOpSegment* segment, bool flipped, bool ordered) { 401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->containsCoincidence(segment)) { 402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* next = &fPtT; 405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((next = next->next()) != &fPtT) { 406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (next->segment() == segment) { 407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpan* span; 408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* base = next->span(); 409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!ordered) { 410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* spanEndPtT = fNext->contains(segment); 411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!spanEndPtT); 412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* spanEnd = spanEndPtT->span(); 413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* start = base->ptT()->starter(spanEnd->ptT()); 414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!start->span()->upCastable()); 415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot span = const_cast<SkOpSpan*>(start->span()->upCast()); 416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (flipped) { 417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot span = base->prev(); 418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!span); 419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!base->upCastable()); 421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot span = base->upCast(); 422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->insertCoincidence(span); 424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COINCIDENCE 428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(0); // FIXME? if we get here, the span is missing its opposite segment... 429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSpan::release(const SkOpPtT* kept) { 434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(fDebugDeleted = true); 435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(kept->span() != this); 436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!final()); 437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpan* prev = this->prev(); 438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(prev); 439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* next = this->next(); 440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(next); 441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot prev->setNext(next); 442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot next->setPrev(prev); 443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->segment()->release(this); 444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpCoincidence* coincidence = this->globalState()->coincidence(); 445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coincidence) { 446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coincidence->fixUp(this->ptT(), kept); 447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->ptT()->setDeleted(); 449fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* stopPtT = this->ptT(); 450fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* testPtT = stopPtT; 451fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* keptSpan = kept->span(); 452fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 453fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this == testPtT->span()) { 454fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot testPtT->setSpan(keptSpan); 455fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 456fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((testPtT = testPtT->next()) != stopPtT); 457fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 458fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 459fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSpan::setOppSum(int oppSum) { 460fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!final()); 461fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fOppSum != SK_MinS32 && fOppSum != oppSum) { 462fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->globalState()->setWindingFailed(); 463fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 464fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 465fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!DEBUG_LIMIT_WIND_SUM || SkTAbs(oppSum) <= DEBUG_LIMIT_WIND_SUM); 466fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fOppSum = oppSum; 467fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 468fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 469fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSpan::setWindSum(int windSum) { 470fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!final()); 471fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fWindSum != SK_MinS32 && fWindSum != windSum) { 472fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->globalState()->setWindingFailed(); 473fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 474fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 475fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!DEBUG_LIMIT_WIND_SUM || SkTAbs(windSum) <= DEBUG_LIMIT_WIND_SUM); 476fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fWindSum = windSum; 477fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 478