1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* 2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2012 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#ifndef SkOpSpan_DEFINED 8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define SkOpSpan_DEFINED 9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPathOpsDebug.h" 11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPathOpsTypes.h" 12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPoint.h" 13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SkArenaAlloc; 15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SkOpAngle; 16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SkOpContour; 17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SkOpGlobalState; 18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SkOpSegment; 19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SkOpSpanBase; 20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SkOpSpan; 21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstruct SkPathOpsBounds; 22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// subset of op span used by terminal span (when t is equal to one) 24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SkOpPtT { 25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic: 26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot enum { 27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kIsAlias = 1, 28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kIsDuplicate = 1 29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* active() const; 32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // please keep in sync with debugAddOpp() 34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void addOpp(SkOpPtT* opp, SkOpPtT* oppPrev) { 35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* oldNext = this->fNext; 36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(this != opp); 37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->fNext = opp; 38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(oppPrev != oldNext); 39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppPrev->fNext = oldNext; 40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool alias() const; 43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool coincident() const { return fCoincident; } 44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool contains(const SkOpPtT* ) const; 45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool contains(const SkOpSegment*, const SkPoint& ) const; 46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool contains(const SkOpSegment*, double t) const; 47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* contains(const SkOpSegment* ) const; 48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpContour* contour() const; 49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int debugID() const { 51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkDEBUGRELEASE(fID, -1); 52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void debugAddOpp(const SkOpPtT* opp, const SkOpPtT* oppPrev) const; 55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpAngle* debugAngle(int id) const; 56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpCoincidence* debugCoincidence() const; 57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool debugContains(const SkOpPtT* ) const; 58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* debugContains(const SkOpSegment* check) const; 59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpContour* debugContour(int id) const; 60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* debugEnder(const SkOpPtT* end) const; 61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int debugLoopLimit(bool report) const; 62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool debugMatchID(int id) const; 63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* debugOppPrev(const SkOpPtT* opp) const; 64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* debugPtT(int id) const; 65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void debugResetCoinT() const; 66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* debugSegment(int id) const; 67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void debugSetCoinT(int ) const; 68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* debugSpan(int id) const; 69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void debugValidate() const; 70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool deleted() const { 72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fDeleted; 73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool duplicate() const { 76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fDuplicatePt; 77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void dump() const; // available to testing only 80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void dumpAll() const; 81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void dumpBase() const; 82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* find(const SkOpSegment* ) const; 84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpGlobalState* globalState() const; 85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void init(SkOpSpanBase* , double t, const SkPoint& , bool dup); 86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void insert(SkOpPtT* span) { 88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(span != this); 89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot span->fNext = fNext; 90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fNext = span; 91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* next() const { 94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fNext; 95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* next() { 98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fNext; 99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool onEnd() const; 102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // returns nullptr if this is already in the opp ptT loop 104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* oppPrev(const SkOpPtT* opp) const { 105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // find the fOpp ptr to opp 106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* oppPrev = opp->fNext; 107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppPrev == this) { 108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (oppPrev->fNext != opp) { 111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppPrev = oppPrev->fNext; 112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppPrev == this) { 113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return oppPrev; 117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static bool Overlaps(const SkOpPtT* s1, const SkOpPtT* e1, const SkOpPtT* s2, 120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* e2, const SkOpPtT** sOut, const SkOpPtT** eOut) { 121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* start1 = s1->fT < e1->fT ? s1 : e1; 122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* start2 = s2->fT < e2->fT ? s2 : e2; 123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *sOut = between(s1->fT, start2->fT, e1->fT) ? start2 124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : between(s2->fT, start1->fT, e2->fT) ? start1 : nullptr; 125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* end1 = s1->fT < e1->fT ? e1 : s1; 126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* end2 = s2->fT < e2->fT ? e2 : s2; 127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *eOut = between(s1->fT, end2->fT, e1->fT) ? end2 128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : between(s2->fT, end1->fT, e2->fT) ? end1 : nullptr; 129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (*sOut == *eOut) { 130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(start1->fT >= end2->fT || start2->fT >= end1->fT); 131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!*sOut || *sOut != *eOut); 134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return *sOut && *eOut; 135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool ptAlreadySeen(const SkOpPtT* head) const; 138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* prev(); 139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* segment() const; 141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSegment* segment(); 142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void setCoincident() const { 144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(!fDeleted); 145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCoincident = true; 146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void setDeleted(); 149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void setSpan(const SkOpSpanBase* span) { 151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fSpan = const_cast<SkOpSpanBase*>(span); 152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* span() const { 155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fSpan; 156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* span() { 159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fSpan; 160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* starter(const SkOpPtT* end) const { 163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fT < end->fT ? this : end; 164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double fT; 167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPoint fPt; // cache of point value at this t 168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprotected: 169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* fSpan; // contains winding data 170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* fNext; // intersection on opposite curve or alias on this curve 171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool fDeleted; // set if removed from span list 172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool fDuplicatePt; // set if identical pt is somewhere in the next loop 173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // below mutable since referrer is otherwise always const 174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot mutable bool fCoincident; // set if at some point a coincident span pointed here 175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(int fID); 176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SkOpSpanBase { 179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic: 180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* active(); 181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void addOpp(SkOpSpanBase* opp); 182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void bumpSpanAdds() { 184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++fSpanAdds; 185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool chased() const { 188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fChased; 189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void checkForCollapsedCoincidence(); 192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* coinEnd() const { 194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fCoinEnd; 195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool collapsed(double s, double e) const; 198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool contains(const SkOpSpanBase* ) const; 199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* contains(const SkOpSegment* ) const; 200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool containsCoinEnd(const SkOpSpanBase* coin) const { 202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(this != coin); 203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* next = this; 204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((next = next->fCoinEnd) != this) { 205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (next == coin) { 206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool containsCoinEnd(const SkOpSegment* ) const; 213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpContour* contour() const; 214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int debugBumpCount() { 216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkDEBUGRELEASE(++fCount, -1); 217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int debugID() const { 220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkDEBUGRELEASE(fID, -1); 221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COIN 224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void debugAddOpp(SkPathOpsDebug::GlitchLog* , const SkOpSpanBase* opp) const; 225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool debugAlignedEnd(double t, const SkPoint& pt) const; 227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool debugAlignedInner() const; 228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpAngle* debugAngle(int id) const; 229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COIN 230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void debugCheckForCollapsedCoincidence(SkPathOpsDebug::GlitchLog* ) const; 231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpCoincidence* debugCoincidence() const; 233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool debugCoinEndLoopCheck() const; 234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpContour* debugContour(int id) const; 235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_DEBUG 236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool debugDeleted() const { return fDebugDeleted; } 237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COIN 239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void debugInsertCoinEnd(SkPathOpsDebug::GlitchLog* , 240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* ) const; 241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void debugMergeMatches(SkPathOpsDebug::GlitchLog* log, 242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* opp) const; 243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* debugPtT(int id) const; 245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void debugResetCoinT() const; 246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* debugSegment(int id) const; 247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void debugSetCoinT(int ) const; 248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_DEBUG 249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void debugSetDeleted() { fDebugDeleted = true; } 250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* debugSpan(int id) const; 252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* debugStarter(SkOpSpanBase const** endPtr) const; 253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpGlobalState* globalState() const; 254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void debugValidate() const; 255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool deleted() const { 257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fPtT.deleted(); 258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void dump() const; // available to testing only 261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void dumpCoin() const; 262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void dumpAll() const; 263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void dumpBase() const; 264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void dumpHead() const; 265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool final() const { 267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fPtT.fT == 1; 268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpAngle* fromAngle() const { 271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fFromAngle; 272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void initBase(SkOpSegment* parent, SkOpSpan* prev, double t, const SkPoint& pt); 275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Please keep this in sync with debugInsertCoinEnd() 277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void insertCoinEnd(SkOpSpanBase* coin) { 278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (containsCoinEnd(coin)) { 279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(coin->containsCoinEnd(this)); 280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot debugValidate(); 283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(this != coin); 284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* coinNext = coin->fCoinEnd; 285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coin->fCoinEnd = this->fCoinEnd; 286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->fCoinEnd = coinNext; 287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot debugValidate(); 288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void merge(SkOpSpan* span); 291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void mergeMatches(SkOpSpanBase* opp); 292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* prev() const { 294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fPrev; 295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpan* prev() { 298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fPrev; 299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPoint& pt() const { 302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fPtT.fPt; 303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ptT() const { 306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return &fPtT; 307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* ptT() { 310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return &fPtT; 311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSegment* segment() const { 314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fSegment; 315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void setAligned() { 318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fAligned = true; 319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void setChased(bool chased) { 322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fChased = chased; 323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void setFromAngle(SkOpAngle* angle) { 326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFromAngle = angle; 327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void setPrev(SkOpSpan* prev) { 330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fPrev = prev; 331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool simple() const { 334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fPtT.debugValidate(); 335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fPtT.next()->next() == &fPtT; 336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int spanAddsCount() const { 339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fSpanAdds; 340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* starter(const SkOpSpanBase* end) const { 343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* result = t() < end->t() ? this : end; 344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return result->upCast(); 345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpan* starter(SkOpSpanBase* end) { 348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(this->segment() == end->segment()); 349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* result = t() < end->t() ? this : end; 350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return result->upCast(); 351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpan* starter(SkOpSpanBase** endPtr) { 354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* end = *endPtr; 355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(this->segment() == end->segment()); 356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* result; 357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (t() < end->t()) { 358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result = this; 359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result = end; 361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *endPtr = this; 362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return result->upCast(); 364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int step(const SkOpSpanBase* end) const { 367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return t() < end->t() ? 1 : -1; 368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double t() const { 371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fPtT.fT; 372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void unaligned() { 375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fAligned = false; 376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpan* upCast() { 379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!final()); 380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return (SkOpSpan*) this; 381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* upCast() const { 384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(!final()); 385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return (const SkOpSpan*) this; 386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpan* upCastable() { 389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return final() ? nullptr : upCast(); 390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* upCastable() const { 393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return final() ? nullptr : upCast(); 394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate: 397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void alignInner(); 398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprotected: // no direct access to internals to avoid treating a span base as a span 400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT fPtT; // list of points and t values associated with the start of this span 401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSegment* fSegment; // segment that contains this span 402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* fCoinEnd; // linked list of coincident spans that end here (may point to itself) 403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpAngle* fFromAngle; // points to next angle from span start to end 404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpan* fPrev; // previous intersection point 405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int fSpanAdds; // number of times intersections have been added to span 406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool fAligned; 407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool fChased; // set after span has been added to chase array 408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(int fCount); // number of pt/t pairs added 409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(int fID); 410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(bool fDebugDeleted); // set when span was merged with another span 411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SkOpSpan : public SkOpSpanBase { 414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic: 415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool alreadyAdded() const { 416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fAlreadyAdded) { 417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fAlreadyAdded = true; 420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool clearCoincident() { 424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!final()); 425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fCoincident == this) { 426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCoincident = this; 429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int computeWindSum(); 433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool containsCoincidence(const SkOpSegment* ) const; 434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool containsCoincidence(const SkOpSpan* coin) const { 436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(this != coin); 437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* next = this; 438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((next = next->fCoincident) != this) { 439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (next == coin) { 440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool debugCoinLoopCheck() const; 447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COIN 448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void debugInsertCoincidence(SkPathOpsDebug::GlitchLog* , const SkOpSpan* ) const; 449fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void debugInsertCoincidence(SkPathOpsDebug::GlitchLog* , 450fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* , bool flipped, bool ordered) const; 451fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 452fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void dumpCoin() const; 453fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool dumpSpan() const; 454fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 455fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool done() const { 456fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!final()); 457fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fDone; 458fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 459fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 460fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void init(SkOpSegment* parent, SkOpSpan* prev, double t, const SkPoint& pt); 461fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool insertCoincidence(const SkOpSegment* , bool flipped, bool ordered); 462fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 463fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Please keep this in sync with debugInsertCoincidence() 464fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void insertCoincidence(SkOpSpan* coin) { 465fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (containsCoincidence(coin)) { 466fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(coin->containsCoincidence(this)); 467fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 468fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 469fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot debugValidate(); 470fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(this != coin); 471fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpan* coinNext = coin->fCoincident; 472fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coin->fCoincident = this->fCoincident; 473fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->fCoincident = coinNext; 474fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot debugValidate(); 475fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 476fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 477fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool isCanceled() const { 478fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!final()); 479fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fWindValue == 0 && fOppValue == 0; 480fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 481fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 482fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool isCoincident() const { 483fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!final()); 484fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fCoincident != this; 485fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 486fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 487fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* next() const { 488fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!final()); 489fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fNext; 490fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 491fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 492fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int oppSum() const { 493fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!final()); 494fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fOppSum; 495fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 496fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 497fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int oppValue() const { 498fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!final()); 499fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fOppValue; 500fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 501fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 502fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void release(const SkOpPtT* ); 503fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 504fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* setCoinStart(SkOpSpan* oldCoinStart, SkOpSegment* oppSegment); 505fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 506fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void setDone(bool done) { 507fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!final()); 508fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDone = done; 509fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 510fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 511fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void setNext(SkOpSpanBase* nextT) { 512fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!final()); 513fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fNext = nextT; 514fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 515fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 516fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void setOppSum(int oppSum); 517fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 518fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void setOppValue(int oppValue) { 519fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!final()); 520fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fOppSum == SK_MinS32); 521fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(!oppValue || !fDone); 522fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fOppValue = oppValue; 523fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 524fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 525fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void setToAngle(SkOpAngle* angle) { 526fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!final()); 527fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fToAngle = angle; 528fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 529fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 530fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void setWindSum(int windSum); 531fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 532fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void setWindValue(int windValue) { 533fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!final()); 534fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(windValue >= 0); 535fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fWindSum == SK_MinS32); 536fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(!windValue || !fDone); 537fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fWindValue = windValue; 538fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 539fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 540fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool sortableTop(SkOpContour* ); 541fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 542fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpAngle* toAngle() const { 543fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!final()); 544fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fToAngle; 545fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 546fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 547fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int windSum() const { 548fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!final()); 549fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fWindSum; 550fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 551fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 552fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int windValue() const { 553fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(!final()); 554fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fWindValue; 555fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 556fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 557fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate: // no direct access to internals to avoid treating a span base as a span 558fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpan* fCoincident; // linked list of spans coincident with this one (may point to itself) 559fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpAngle* fToAngle; // points to next angle from span start to end 560fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* fNext; // next intersection point 561fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int fWindSum; // accumulated from contours surrounding this one. 562fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int fOppSum; // for binary operators: the opposite winding sum 563fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int fWindValue; // 0 == canceled; 1 == normal; >1 == coincident 564fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int fOppValue; // normally 0 -- when binary coincident edges combine, opp value goes here 565fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int fTopTTry; // specifies direction and t value to try next 566fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool fDone; // if set, this span to next higher T has been processed 567fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot mutable bool fAlreadyAdded; 568fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 569fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 570fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 571