| Index: src/pathops/SkPathOpsTSect.h
|
| diff --git a/src/pathops/SkPathOpsTSect.h b/src/pathops/SkPathOpsTSect.h
|
| index 9d634333301e180c1121a28f2e4734b06cce362e..ffd69951d3f5fc5af6d9aa33dd1fe30e27929d6b 100644
|
| --- a/src/pathops/SkPathOpsTSect.h
|
| +++ b/src/pathops/SkPathOpsTSect.h
|
| @@ -8,16 +8,15 @@
|
| #include "SkChunkAlloc.h"
|
| #include "SkPathOpsBounds.h"
|
| #include "SkPathOpsRect.h"
|
| -#include "SkPathOpsQuad.h"
|
| #include "SkIntersections.h"
|
| #include "SkTSort.h"
|
|
|
| -/* TCurve is either SkDQuadratic or SkDCubic */
|
| -template<typename TCurve>
|
| +/* TCurve and OppCurve are one of { SkDQuadratic, SkDConic, SkDCubic } */
|
| +template<typename TCurve, typename OppCurve>
|
| class SkTCoincident {
|
| public:
|
| SkTCoincident() {
|
| - clear();
|
| + this->clear();
|
| }
|
|
|
| void clear() {
|
| @@ -25,12 +24,19 @@ public:
|
| fCoincident = false;
|
| }
|
|
|
| + void debugInit() {
|
| + this->clear();
|
| + fPerpPt.fX = fPerpPt.fY = SK_ScalarNaN;
|
| + }
|
| +
|
| + void dump() const;
|
| +
|
| bool isCoincident() const {
|
| return fCoincident;
|
| }
|
|
|
| void init() {
|
| - clear();
|
| + this->clear();
|
| SkDEBUGCODE(fPerpPt.fX = fPerpPt.fY = SK_ScalarNaN);
|
| }
|
|
|
| @@ -49,7 +55,7 @@ public:
|
| return fPerpT;
|
| }
|
|
|
| - void setPerp(const TCurve& c1, double t, const SkDPoint& cPt, const TCurve& );
|
| + void setPerp(const TCurve& c1, double t, const SkDPoint& cPt, const OppCurve& );
|
|
|
| private:
|
| SkDPoint fPerpPt;
|
| @@ -57,40 +63,51 @@ private:
|
| bool fCoincident;
|
| };
|
|
|
| -template<typename TCurve> class SkTSect;
|
| -template<typename TCurve> class SkTSpan;
|
| +template<typename TCurve, typename OppCurve> class SkTSect;
|
| +template<typename TCurve, typename OppCurve> class SkTSpan;
|
|
|
| -template<typename TCurve>
|
| +template<typename TCurve, typename OppCurve>
|
| struct SkTSpanBounded {
|
| - SkTSpan<TCurve>* fBounded;
|
| + SkTSpan<TCurve, OppCurve>* fBounded;
|
| SkTSpanBounded* fNext;
|
| };
|
|
|
| /* Curve is either TCurve or SkDCubic */
|
| -template<typename TCurve>
|
| +template<typename TCurve, typename OppCurve>
|
| class SkTSpan {
|
| public:
|
| - void addBounded(SkTSpan* , SkChunkAlloc* );
|
| + void addBounded(SkTSpan<OppCurve, TCurve>* , SkChunkAlloc* );
|
| double closestBoundedT(const SkDPoint& pt) const;
|
| bool contains(double t) const;
|
|
|
| - const SkTSect<TCurve>* debugOpp() const;
|
| + void debugInit() {
|
| + TCurve dummy;
|
| + dummy.debugInit();
|
| + init(dummy);
|
| + initBounds(dummy);
|
| + fCoinStart.debugInit();
|
| + fCoinEnd.debugInit();
|
| + }
|
| +
|
| + const SkTSect<OppCurve, TCurve>* debugOpp() const;
|
| const SkTSpan* debugSpan(int ) const;
|
| const SkTSpan* debugT(double t) const;
|
| #ifdef SK_DEBUG
|
| bool debugIsBefore(const SkTSpan* span) const;
|
| #endif
|
| void dump() const;
|
| - void dumpBounds(int id) const;
|
| + void dumpBounded(int id) const;
|
| + void dumpBounds() const;
|
| + void dumpCoin() const;
|
|
|
| double endT() const {
|
| return fEndT;
|
| }
|
|
|
| - SkTSpan* findOppSpan(const SkTSpan* opp) const;
|
| + SkTSpan<OppCurve, TCurve>* findOppSpan(const SkTSpan<OppCurve, TCurve>* opp) const;
|
|
|
| - SkTSpan* findOppT(double t) const {
|
| - SkTSpan* result = oppT(t);
|
| + SkTSpan<OppCurve, TCurve>* findOppT(double t) const {
|
| + SkTSpan<OppCurve, TCurve>* result = oppT(t);
|
| SkASSERT(result);
|
| return result;
|
| }
|
| @@ -99,7 +116,7 @@ public:
|
| return SkToBool(oppT(t));
|
| }
|
|
|
| - int hullsIntersect(SkTSpan* span, bool* start, bool* oppStart);
|
| + int hullsIntersect(SkTSpan<OppCurve, TCurve>* span, bool* start, bool* oppStart);
|
| void init(const TCurve& );
|
| void initBounds(const TCurve& );
|
|
|
| @@ -107,7 +124,7 @@ public:
|
| return fBounded != NULL;
|
| }
|
|
|
| - bool linearsIntersect(SkTSpan* span);
|
| + bool linearsIntersect(SkTSpan<OppCurve, TCurve>* span);
|
| double linearT(const SkDPoint& ) const;
|
|
|
| void markCoincident() {
|
| @@ -119,14 +136,15 @@ public:
|
| return fNext;
|
| }
|
|
|
| - bool onlyEndPointsInCommon(const SkTSpan* opp, bool* start, bool* oppStart, bool* ptsInCommon);
|
| + bool onlyEndPointsInCommon(const SkTSpan<OppCurve, TCurve>* opp, bool* start,
|
| + bool* oppStart, bool* ptsInCommon);
|
|
|
| const TCurve& part() const {
|
| return fPart;
|
| }
|
|
|
| bool removeAllBounded();
|
| - bool removeBounded(const SkTSpan* opp);
|
| + bool removeBounded(const SkTSpan<OppCurve, TCurve>* opp);
|
|
|
| void reset() {
|
| fBounded = NULL;
|
| @@ -156,9 +174,9 @@ private:
|
|
|
| void dumpID() const;
|
|
|
| - int hullCheck(const SkTSpan* opp, bool* start, bool* oppStart);
|
| - int linearIntersects(const TCurve& ) const;
|
| - SkTSpan* oppT(double t) const;
|
| + int hullCheck(const SkTSpan<OppCurve, TCurve>* opp, bool* start, bool* oppStart);
|
| + int linearIntersects(const OppCurve& ) const;
|
| + SkTSpan<OppCurve, TCurve>* oppT(double t) const;
|
|
|
| void validate() const;
|
| void validateBounded() const;
|
| @@ -166,9 +184,9 @@ private:
|
| void validatePerpPt(double t, const SkDPoint& ) const;
|
|
|
| TCurve fPart;
|
| - SkTCoincident<TCurve> fCoinStart;
|
| - SkTCoincident<TCurve> fCoinEnd;
|
| - SkTSpanBounded<TCurve>* fBounded;
|
| + SkTCoincident<TCurve, OppCurve> fCoinStart;
|
| + SkTCoincident<TCurve, OppCurve> fCoinEnd;
|
| + SkTSpanBounded<OppCurve, TCurve>* fBounded;
|
| SkTSpan* fPrev;
|
| SkTSpan* fNext;
|
| SkDRect fBounds;
|
| @@ -180,29 +198,33 @@ private:
|
| bool fIsLinear;
|
| bool fIsLine;
|
| bool fDeleted;
|
| - PATH_OPS_DEBUG_CODE(SkTSect<TCurve>* fDebugSect);
|
| + SkDEBUGCODE_(SkTSect<TCurve, OppCurve>* fDebugSect);
|
| PATH_OPS_DEBUG_T_SECT_CODE(int fID);
|
| - friend class SkTSect<TCurve>;
|
| + friend class SkTSect<TCurve, OppCurve>;
|
| + friend class SkTSect<OppCurve, TCurve>;
|
| + friend class SkTSpan<OppCurve, TCurve>;
|
| };
|
|
|
| -template<typename TCurve>
|
| +template<typename TCurve, typename OppCurve>
|
| class SkTSect {
|
| public:
|
| SkTSect(const TCurve& c PATH_OPS_DEBUG_T_SECT_PARAMS(int id));
|
| - static void BinarySearch(SkTSect* sect1, SkTSect* sect2, SkIntersections* intersections);
|
| + static void BinarySearch(SkTSect* sect1, SkTSect<OppCurve, TCurve>* sect2,
|
| + SkIntersections* intersections);
|
|
|
| // for testing only
|
| - bool debugHasBounded(const SkTSpan<TCurve>* ) const;
|
| + bool debugHasBounded(const SkTSpan<OppCurve, TCurve>* ) const;
|
|
|
| - const SkTSect* debugOpp() const {
|
| - return PATH_OPS_DEBUG_RELEASE(fOppSect, NULL);
|
| + const SkTSect<OppCurve, TCurve>* debugOpp() const {
|
| + return SkDEBUGRELEASE(fOppSect, NULL);
|
| }
|
|
|
| - const SkTSpan<TCurve>* debugSpan(int id) const;
|
| - const SkTSpan<TCurve>* debugT(double t) const;
|
| + const SkTSpan<TCurve, OppCurve>* debugSpan(int id) const;
|
| + const SkTSpan<TCurve, OppCurve>* debugT(double t) const;
|
| void dump() const;
|
| - void dumpBoth(SkTSect* ) const;
|
| - void dumpBounds(int id) const;
|
| + void dumpBoth(SkTSect<OppCurve, TCurve>* ) const;
|
| + void dumpBounded(int id) const;
|
| + void dumpBounds() const;
|
| void dumpCoin() const;
|
| void dumpCoinCurves() const;
|
| void dumpCurves() const;
|
| @@ -215,82 +237,92 @@ private:
|
| kOneS2Set = 8
|
| };
|
|
|
| - SkTSpan<TCurve>* addFollowing(SkTSpan<TCurve>* prior);
|
| - void addForPerp(SkTSpan<TCurve>* span, double t);
|
| - SkTSpan<TCurve>* addOne();
|
| + SkTSpan<TCurve, OppCurve>* addFollowing(SkTSpan<TCurve, OppCurve>* prior);
|
| + void addForPerp(SkTSpan<OppCurve, TCurve>* span, double t);
|
| + SkTSpan<TCurve, OppCurve>* addOne();
|
|
|
| - SkTSpan<TCurve>* addSplitAt(SkTSpan<TCurve>* span, double t) {
|
| - SkTSpan<TCurve>* result = this->addOne();
|
| + SkTSpan<TCurve, OppCurve>* addSplitAt(SkTSpan<TCurve, OppCurve>* span, double t) {
|
| + SkTSpan<TCurve, OppCurve>* result = this->addOne();
|
| result->splitAt(span, t, &fHeap);
|
| result->initBounds(fCurve);
|
| span->initBounds(fCurve);
|
| return result;
|
| }
|
|
|
| - bool binarySearchCoin(SkTSect* , double tStart, double tStep, double* t, double* oppT);
|
| - SkTSpan<TCurve>* boundsMax() const;
|
| - void coincidentCheck(SkTSect* sect2);
|
| + bool binarySearchCoin(SkTSect<OppCurve, TCurve>* , double tStart, double tStep, double* t,
|
| + double* oppT);
|
| + SkTSpan<TCurve, OppCurve>* boundsMax() const;
|
| + void coincidentCheck(SkTSect<OppCurve, TCurve>* sect2);
|
| bool coincidentHasT(double t);
|
| - void computePerpendiculars(SkTSect* sect2, SkTSpan<TCurve>* first, SkTSpan<TCurve>* last);
|
| - int countConsecutiveSpans(SkTSpan<TCurve>* first, SkTSpan<TCurve>** last) const;
|
| + int collapsed() const;
|
| + void computePerpendiculars(SkTSect<OppCurve, TCurve>* sect2, SkTSpan<TCurve, OppCurve>* first,
|
| + SkTSpan<TCurve, OppCurve>* last);
|
| + int countConsecutiveSpans(SkTSpan<TCurve, OppCurve>* first,
|
| + SkTSpan<TCurve, OppCurve>** last) const;
|
|
|
| int debugID() const {
|
| return PATH_OPS_DEBUG_T_SECT_RELEASE(fID, -1);
|
| }
|
|
|
| void deleteEmptySpans();
|
| - void dumpCommon(const SkTSpan<TCurve>* ) const;
|
| - void dumpCommonCurves(const SkTSpan<TCurve>* ) const;
|
| - static int EndsEqual(const SkTSect* sect1, const SkTSect* sect2, SkIntersections* );
|
| - SkTSpan<TCurve>* extractCoincident(SkTSect* sect2, SkTSpan<TCurve>* first,
|
| - SkTSpan<TCurve>* last);
|
| - SkTSpan<TCurve>* findCoincidentRun(SkTSpan<TCurve>* first, SkTSpan<TCurve>** lastPtr,
|
| - const SkTSect* sect2);
|
| - int intersects(SkTSpan<TCurve>* span, const SkTSect* opp,
|
| - SkTSpan<TCurve>* oppSpan, int* oppResult) const;
|
| - int linesIntersect(const SkTSpan<TCurve>* span, const SkTSect* opp,
|
| - const SkTSpan<TCurve>* oppSpan, SkIntersections* ) const;
|
| - void markSpanGone(SkTSpan<TCurve>* span);
|
| - bool matchedDirection(double t, const SkTSect* sect2, double t2) const;
|
| - void matchedDirCheck(double t, const SkTSect* sect2, double t2,
|
| + void dumpCommon(const SkTSpan<TCurve, OppCurve>* ) const;
|
| + void dumpCommonCurves(const SkTSpan<TCurve, OppCurve>* ) const;
|
| + static int EndsEqual(const SkTSect* sect1, const SkTSect<OppCurve, TCurve>* sect2,
|
| + SkIntersections* );
|
| + SkTSpan<TCurve, OppCurve>* extractCoincident(SkTSect<OppCurve, TCurve>* sect2,
|
| + SkTSpan<TCurve, OppCurve>* first,
|
| + SkTSpan<TCurve, OppCurve>* last);
|
| + SkTSpan<TCurve, OppCurve>* findCoincidentRun(SkTSpan<TCurve, OppCurve>* first,
|
| + SkTSpan<TCurve, OppCurve>** lastPtr);
|
| + int intersects(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp,
|
| + SkTSpan<OppCurve, TCurve>* oppSpan, int* oppResult);
|
| + int linesIntersect(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp,
|
| + SkTSpan<OppCurve, TCurve>* oppSpan, SkIntersections* );
|
| + void markSpanGone(SkTSpan<TCurve, OppCurve>* span);
|
| + bool matchedDirection(double t, const SkTSect<OppCurve, TCurve>* sect2, double t2) const;
|
| + void matchedDirCheck(double t, const SkTSect<OppCurve, TCurve>* sect2, double t2,
|
| bool* calcMatched, bool* oppMatched) const;
|
| - void mergeCoincidence(SkTSect* sect2);
|
| - SkTSpan<TCurve>* prev(SkTSpan<TCurve>* ) const;
|
| - void removeByPerpendicular(SkTSect* opp);
|
| + void mergeCoincidence(SkTSect<OppCurve, TCurve>* sect2);
|
| + SkTSpan<TCurve, OppCurve>* prev(SkTSpan<TCurve, OppCurve>* ) const;
|
| + void removeByPerpendicular(SkTSect<OppCurve, TCurve>* opp);
|
| void recoverCollapsed();
|
| - void removeCoincident(SkTSpan<TCurve>* span, bool isBetween);
|
| - void removeAllBut(const SkTSpan<TCurve>* keep, SkTSpan<TCurve>* span, SkTSect* opp);
|
| - void removeSpan(SkTSpan<TCurve>* span);
|
| - void removeSpanRange(SkTSpan<TCurve>* first, SkTSpan<TCurve>* last);
|
| - void removeSpans(SkTSpan<TCurve>* span, SkTSect* opp);
|
| - SkTSpan<TCurve>* spanAtT(double t, SkTSpan<TCurve>** priorSpan);
|
| - SkTSpan<TCurve>* tail();
|
| - void trim(SkTSpan<TCurve>* span, SkTSect* opp);
|
| - void unlinkSpan(SkTSpan<TCurve>* span);
|
| - bool updateBounded(SkTSpan<TCurve>* first, SkTSpan<TCurve>* last, SkTSpan<TCurve>* oppFirst);
|
| + void removeCoincident(SkTSpan<TCurve, OppCurve>* span, bool isBetween);
|
| + void removeAllBut(const SkTSpan<OppCurve, TCurve>* keep, SkTSpan<TCurve, OppCurve>* span,
|
| + SkTSect<OppCurve, TCurve>* opp);
|
| + void removeSpan(SkTSpan<TCurve, OppCurve>* span);
|
| + void removeSpanRange(SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last);
|
| + void removeSpans(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp);
|
| + SkTSpan<TCurve, OppCurve>* spanAtT(double t, SkTSpan<TCurve, OppCurve>** priorSpan);
|
| + SkTSpan<TCurve, OppCurve>* tail();
|
| + void trim(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp);
|
| + void unlinkSpan(SkTSpan<TCurve, OppCurve>* span);
|
| + bool updateBounded(SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last,
|
| + SkTSpan<OppCurve, TCurve>* oppFirst);
|
| void validate() const;
|
| void validateBounded() const;
|
|
|
| const TCurve& fCurve;
|
| SkChunkAlloc fHeap;
|
| - SkTSpan<TCurve>* fHead;
|
| - SkTSpan<TCurve>* fCoincident;
|
| - SkTSpan<TCurve>* fDeleted;
|
| + SkTSpan<TCurve, OppCurve>* fHead;
|
| + SkTSpan<TCurve, OppCurve>* fCoincident;
|
| + SkTSpan<TCurve, OppCurve>* fDeleted;
|
| int fActiveCount;
|
| - PATH_OPS_DEBUG_CODE(SkTSect* fOppSect);
|
| + SkDEBUGCODE_(SkTSect<OppCurve, TCurve>* fOppSect);
|
| PATH_OPS_DEBUG_T_SECT_CODE(int fID);
|
| PATH_OPS_DEBUG_T_SECT_CODE(int fDebugCount);
|
| #if DEBUG_T_SECT
|
| int fDebugAllocatedCount;
|
| #endif
|
| - friend class SkTSpan<TCurve>; // only used by debug id
|
| + friend class SkTSpan<TCurve, OppCurve>;
|
| + friend class SkTSpan<OppCurve, TCurve>;
|
| + friend class SkTSect<OppCurve, TCurve>;
|
| };
|
|
|
| #define COINCIDENT_SPAN_COUNT 9
|
|
|
| -template<typename TCurve>
|
| -void SkTCoincident<TCurve>::setPerp(const TCurve& c1, double t,
|
| - const SkDPoint& cPt, const TCurve& c2) {
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTCoincident<TCurve, OppCurve>::setPerp(const TCurve& c1, double t,
|
| + const SkDPoint& cPt, const OppCurve& c2) {
|
| SkDVector dxdy = c1.dxdyAtT(t);
|
| SkDLine perp = {{ cPt, {cPt.fX + dxdy.fY, cPt.fY - dxdy.fX} }};
|
| SkIntersections i;
|
| @@ -312,8 +344,9 @@ void SkTCoincident<TCurve>::setPerp(const TCurve& c1, double t,
|
| }
|
| }
|
| #if DEBUG_T_SECT
|
| - SkDebugf("%s cPt=(%1.9g,%1.9g) %s fPerpPt=(%1.9g,%1.9g)\n", __FUNCTION__, cPt.fX, cPt.fY,
|
| - cPt.approximatelyEqual(fPerpPt) ? "==" : "!=", fPerpPt.fX, fPerpPt.fY);
|
| + SkDebugf("setPerp t=%1.9g cPt=(%1.9g,%1.9g) %s oppT=%1.9g fPerpPt=(%1.9g,%1.9g)\n",
|
| + t, cPt.fX, cPt.fY,
|
| + cPt.approximatelyEqual(fPerpPt) ? "==" : "!=", fPerpT, fPerpPt.fX, fPerpPt.fY);
|
| #endif
|
| fCoincident = cPt.approximatelyEqual(fPerpPt);
|
| #if DEBUG_T_SECT
|
| @@ -323,20 +356,21 @@ void SkTCoincident<TCurve>::setPerp(const TCurve& c1, double t,
|
| #endif
|
| }
|
|
|
| -template<typename TCurve>
|
| -void SkTSpan<TCurve>::addBounded(SkTSpan* span, SkChunkAlloc* heap) {
|
| - SkTSpanBounded<TCurve>* bounded = SkNEW_PLACEMENT(heap->allocThrow(
|
| - sizeof(SkTSpanBounded<TCurve>)), SkTSpanBounded<TCurve>);
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTSpan<TCurve, OppCurve>::addBounded(SkTSpan<OppCurve, TCurve>* span, SkChunkAlloc* heap) {
|
| + SkTSpanBounded<OppCurve, TCurve>* bounded = SkNEW_PLACEMENT(heap->allocThrow(
|
| + sizeof(SkTSpanBounded<OppCurve, TCurve>)), (SkTSpanBounded<OppCurve, TCurve>));
|
| bounded->fBounded = span;
|
| bounded->fNext = fBounded;
|
| fBounded = bounded;
|
| }
|
|
|
| -template<typename TCurve>
|
| -SkTSpan<TCurve>* SkTSect<TCurve>::addFollowing(SkTSpan<TCurve>* prior) {
|
| - SkTSpan<TCurve>* result = this->addOne();
|
| +template<typename TCurve, typename OppCurve>
|
| +SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::addFollowing(
|
| + SkTSpan<TCurve, OppCurve>* prior) {
|
| + SkTSpan<TCurve, OppCurve>* result = this->addOne();
|
| result->fStartT = prior ? prior->fEndT : 0;
|
| - SkTSpan<TCurve>* next = prior ? prior->fNext : fHead;
|
| + SkTSpan<TCurve, OppCurve>* next = prior ? prior->fNext : fHead;
|
| result->fEndT = next ? next->fStartT : 1;
|
| result->fPrev = prior;
|
| result->fNext = next;
|
| @@ -352,11 +386,11 @@ SkTSpan<TCurve>* SkTSect<TCurve>::addFollowing(SkTSpan<TCurve>* prior) {
|
| return result;
|
| }
|
|
|
| -template<typename TCurve>
|
| -void SkTSect<TCurve>::addForPerp(SkTSpan<TCurve>* span, double t) {
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTSect<TCurve, OppCurve>::addForPerp(SkTSpan<OppCurve, TCurve>* span, double t) {
|
| if (!span->hasOppT(t)) {
|
| - SkTSpan<TCurve>* priorSpan;
|
| - SkTSpan<TCurve>* opp = this->spanAtT(t, &priorSpan);
|
| + SkTSpan<TCurve, OppCurve>* priorSpan;
|
| + SkTSpan<TCurve, OppCurve>* opp = this->spanAtT(t, &priorSpan);
|
| if (!opp) {
|
| opp = this->addFollowing(priorSpan);
|
| #if DEBUG_PERP
|
| @@ -373,22 +407,24 @@ void SkTSect<TCurve>::addForPerp(SkTSpan<TCurve>* span, double t) {
|
| span->addBounded(opp, &fHeap);
|
| }
|
| this->validate();
|
| +#if DEBUG_T_SECT
|
| span->validatePerpT(t);
|
| +#endif
|
| }
|
|
|
| -template<typename TCurve>
|
| -double SkTSpan<TCurve>::closestBoundedT(const SkDPoint& pt) const {
|
| +template<typename TCurve, typename OppCurve>
|
| +double SkTSpan<TCurve, OppCurve>::closestBoundedT(const SkDPoint& pt) const {
|
| double result = -1;
|
| double closest = FLT_MAX;
|
| - const SkTSpanBounded<TCurve>* testBounded = fBounded;
|
| + const SkTSpanBounded<OppCurve, TCurve>* testBounded = fBounded;
|
| while (testBounded) {
|
| - const SkTSpan* test = testBounded->fBounded;
|
| + const SkTSpan<OppCurve, TCurve>* test = testBounded->fBounded;
|
| double startDist = test->fPart[0].distanceSquared(pt);
|
| if (closest > startDist) {
|
| closest = startDist;
|
| result = test->fStartT;
|
| }
|
| - double endDist = test->fPart[TCurve::kPointLast].distanceSquared(pt);
|
| + double endDist = test->fPart[OppCurve::kPointLast].distanceSquared(pt);
|
| if (closest > endDist) {
|
| closest = endDist;
|
| result = test->fEndT;
|
| @@ -400,8 +436,8 @@ double SkTSpan<TCurve>::closestBoundedT(const SkDPoint& pt) const {
|
| }
|
|
|
| #ifdef SK_DEBUG
|
| -template<typename TCurve>
|
| -bool SkTSpan<TCurve>::debugIsBefore(const SkTSpan* span) const {
|
| +template<typename TCurve, typename OppCurve>
|
| +bool SkTSpan<TCurve, OppCurve>::debugIsBefore(const SkTSpan* span) const {
|
| const SkTSpan* work = this;
|
| do {
|
| if (span == work) {
|
| @@ -412,8 +448,8 @@ bool SkTSpan<TCurve>::debugIsBefore(const SkTSpan* span) const {
|
| }
|
| #endif
|
|
|
| -template<typename TCurve>
|
| -bool SkTSpan<TCurve>::contains(double t) const {
|
| +template<typename TCurve, typename OppCurve>
|
| +bool SkTSpan<TCurve, OppCurve>::contains(double t) const {
|
| const SkTSpan* work = this;
|
| do {
|
| if (between(work->fStartT, t, work->fEndT)) {
|
| @@ -423,16 +459,17 @@ bool SkTSpan<TCurve>::contains(double t) const {
|
| return false;
|
| }
|
|
|
| -template<typename TCurve>
|
| -const SkTSect<TCurve>* SkTSpan<TCurve>::debugOpp() const {
|
| - return PATH_OPS_DEBUG_RELEASE(fDebugSect->debugOpp(), NULL);
|
| +template<typename TCurve, typename OppCurve>
|
| +const SkTSect<OppCurve, TCurve>* SkTSpan<TCurve, OppCurve>::debugOpp() const {
|
| + return SkDEBUGRELEASE(fDebugSect->debugOpp(), NULL);
|
| }
|
|
|
| -template<typename TCurve>
|
| -SkTSpan<TCurve>* SkTSpan<TCurve>::findOppSpan(const SkTSpan* opp) const {
|
| - SkTSpanBounded<TCurve>* bounded = fBounded;
|
| +template<typename TCurve, typename OppCurve>
|
| +SkTSpan<OppCurve, TCurve>* SkTSpan<TCurve, OppCurve>::findOppSpan(
|
| + const SkTSpan<OppCurve, TCurve>* opp) const {
|
| + SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
|
| while (bounded) {
|
| - SkTSpan* test = bounded->fBounded;
|
| + SkTSpan<OppCurve, TCurve>* test = bounded->fBounded;
|
| if (opp == test) {
|
| return test;
|
| }
|
| @@ -445,8 +482,9 @@ SkTSpan<TCurve>* SkTSpan<TCurve>::findOppSpan(const SkTSpan* opp) const {
|
| // 1 if hulls intersect
|
| // 2 if hulls only share a common endpoint
|
| // -1 if linear and further checking is required
|
| -template<typename TCurve>
|
| -int SkTSpan<TCurve>::hullCheck(const SkTSpan* opp, bool* start, bool* oppStart) {
|
| +template<typename TCurve, typename OppCurve>
|
| +int SkTSpan<TCurve, OppCurve>::hullCheck(const SkTSpan<OppCurve, TCurve>* opp,
|
| + bool* start, bool* oppStart) {
|
| if (fIsLinear) {
|
| return -1;
|
| }
|
| @@ -472,8 +510,9 @@ int SkTSpan<TCurve>::hullCheck(const SkTSpan* opp, bool* start, bool* oppStart)
|
| // OPTIMIZE ? If at_most_end_pts_in_common detects that one quad is near linear,
|
| // use line intersection to guess a better split than 0.5
|
| // OPTIMIZE Once at_most_end_pts_in_common detects linear, mark span so all future splits are linear
|
| -template<typename TCurve>
|
| -int SkTSpan<TCurve>::hullsIntersect(SkTSpan* opp, bool* start, bool* oppStart) {
|
| +template<typename TCurve, typename OppCurve>
|
| +int SkTSpan<TCurve, OppCurve>::hullsIntersect(SkTSpan<OppCurve, TCurve>* opp,
|
| + bool* start, bool* oppStart) {
|
| if (!fBounds.intersects(opp->fBounds)) {
|
| return 0;
|
| }
|
| @@ -488,8 +527,8 @@ int SkTSpan<TCurve>::hullsIntersect(SkTSpan* opp, bool* start, bool* oppStart) {
|
| return -1;
|
| }
|
|
|
| -template<typename TCurve>
|
| -void SkTSpan<TCurve>::init(const TCurve& c) {
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTSpan<TCurve, OppCurve>::init(const TCurve& c) {
|
| fPrev = fNext = NULL;
|
| fStartT = 0;
|
| fEndT = 1;
|
| @@ -497,8 +536,8 @@ void SkTSpan<TCurve>::init(const TCurve& c) {
|
| resetBounds(c);
|
| }
|
|
|
| -template<typename TCurve>
|
| -void SkTSpan<TCurve>::initBounds(const TCurve& c) {
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTSpan<TCurve, OppCurve>::initBounds(const TCurve& c) {
|
| fPart = c.subDivide(fStartT, fEndT);
|
| fBounds.setBounds(fPart);
|
| fCoinStart.init();
|
| @@ -514,8 +553,8 @@ void SkTSpan<TCurve>::initBounds(const TCurve& c) {
|
| #endif
|
| }
|
|
|
| -template<typename TCurve>
|
| -bool SkTSpan<TCurve>::linearsIntersect(SkTSpan* span) {
|
| +template<typename TCurve, typename OppCurve>
|
| +bool SkTSpan<TCurve, OppCurve>::linearsIntersect(SkTSpan<OppCurve, TCurve>* span) {
|
| int result = this->linearIntersects(span->fPart);
|
| if (result <= 1) {
|
| return SkToBool(result);
|
| @@ -526,16 +565,16 @@ bool SkTSpan<TCurve>::linearsIntersect(SkTSpan* span) {
|
| return SkToBool(result);
|
| }
|
|
|
| -template<typename TCurve>
|
| -double SkTSpan<TCurve>::linearT(const SkDPoint& pt) const {
|
| +template<typename TCurve, typename OppCurve>
|
| +double SkTSpan<TCurve, OppCurve>::linearT(const SkDPoint& pt) const {
|
| SkDVector len = fPart[TCurve::kPointLast] - fPart[0];
|
| return fabs(len.fX) > fabs(len.fY)
|
| ? (pt.fX - fPart[0].fX) / len.fX
|
| : (pt.fY - fPart[0].fY) / len.fY;
|
| }
|
|
|
| -template<typename TCurve>
|
| -int SkTSpan<TCurve>::linearIntersects(const TCurve& q2) const {
|
| +template<typename TCurve, typename OppCurve>
|
| +int SkTSpan<TCurve, OppCurve>::linearIntersects(const OppCurve& q2) const {
|
| // looks like q1 is near-linear
|
| int start = 0, end = TCurve::kPointLast; // the outside points are usually the extremes
|
| if (!fPart.controlsInside()) {
|
| @@ -559,7 +598,7 @@ int SkTSpan<TCurve>::linearIntersects(const TCurve& q2) const {
|
| double opp = fPart[end].fY - origY;
|
| double maxPart = SkTMax(fabs(adj), fabs(opp));
|
| double sign = 0; // initialization to shut up warning in release build
|
| - for (int n = 0; n < TCurve::kPointCount; ++n) {
|
| + for (int n = 0; n < OppCurve::kPointCount; ++n) {
|
| double dx = q2[n].fY - origY;
|
| double dy = q2[n].fX - origX;
|
| double maxVal = SkTMax(maxPart, SkTMax(fabs(dx), fabs(dy)));
|
| @@ -581,33 +620,33 @@ int SkTSpan<TCurve>::linearIntersects(const TCurve& q2) const {
|
| return 0;
|
| }
|
|
|
| -template<typename TCurve>
|
| -bool SkTSpan<TCurve>::onlyEndPointsInCommon(const SkTSpan* opp, bool* start, bool* oppStart,
|
| - bool* ptsInCommon) {
|
| +template<typename TCurve, typename OppCurve>
|
| +bool SkTSpan<TCurve, OppCurve>::onlyEndPointsInCommon(const SkTSpan<OppCurve, TCurve>* opp,
|
| + bool* start, bool* oppStart, bool* ptsInCommon) {
|
| if (opp->fPart[0] == fPart[0]) {
|
| *start = *oppStart = true;
|
| } else if (opp->fPart[0] == fPart[TCurve::kPointLast]) {
|
| *start = false;
|
| *oppStart = true;
|
| - } else if (opp->fPart[TCurve::kPointLast] == fPart[0]) {
|
| + } else if (opp->fPart[OppCurve::kPointLast] == fPart[0]) {
|
| *start = true;
|
| *oppStart = false;
|
| - } else if (opp->fPart[TCurve::kPointLast] == fPart[TCurve::kPointLast]) {
|
| + } else if (opp->fPart[OppCurve::kPointLast] == fPart[TCurve::kPointLast]) {
|
| *start = *oppStart = false;
|
| } else {
|
| *ptsInCommon = false;
|
| return false;
|
| }
|
| *ptsInCommon = true;
|
| - const SkDPoint* o1Pts[TCurve::kPointCount - 1], * o2Pts[TCurve::kPointCount - 1];
|
| + const SkDPoint* otherPts[TCurve::kPointCount - 1], * oppOtherPts[OppCurve::kPointCount - 1];
|
| int baseIndex = *start ? 0 : TCurve::kPointLast;
|
| - fPart.otherPts(baseIndex, o1Pts);
|
| - opp->fPart.otherPts(*oppStart ? 0 : TCurve::kPointLast, o2Pts);
|
| + fPart.otherPts(baseIndex, otherPts);
|
| + opp->fPart.otherPts(*oppStart ? 0 : OppCurve::kPointLast, oppOtherPts);
|
| const SkDPoint& base = fPart[baseIndex];
|
| - for (int o1 = 0; o1 < (int) SK_ARRAY_COUNT(o1Pts); ++o1) {
|
| - SkDVector v1 = *o1Pts[o1] - base;
|
| - for (int o2 = 0; o2 < (int) SK_ARRAY_COUNT(o2Pts); ++o2) {
|
| - SkDVector v2 = *o2Pts[o2] - base;
|
| + for (int o1 = 0; o1 < (int) SK_ARRAY_COUNT(otherPts); ++o1) {
|
| + SkDVector v1 = *otherPts[o1] - base;
|
| + for (int o2 = 0; o2 < (int) SK_ARRAY_COUNT(oppOtherPts); ++o2) {
|
| + SkDVector v2 = *oppOtherPts[o2] - base;
|
| if (v2.dot(v1) >= 0) {
|
| return false;
|
| }
|
| @@ -616,11 +655,11 @@ bool SkTSpan<TCurve>::onlyEndPointsInCommon(const SkTSpan* opp, bool* start, boo
|
| return true;
|
| }
|
|
|
| -template<typename TCurve>
|
| -SkTSpan<TCurve>* SkTSpan<TCurve>::oppT(double t) const {
|
| - SkTSpanBounded<TCurve>* bounded = fBounded;
|
| +template<typename TCurve, typename OppCurve>
|
| +SkTSpan<OppCurve, TCurve>* SkTSpan<TCurve, OppCurve>::oppT(double t) const {
|
| + SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
|
| while (bounded) {
|
| - SkTSpan* test = bounded->fBounded;
|
| + SkTSpan<OppCurve, TCurve>* test = bounded->fBounded;
|
| if (between(test->fStartT, t, test->fEndT)) {
|
| return test;
|
| }
|
| @@ -629,26 +668,26 @@ SkTSpan<TCurve>* SkTSpan<TCurve>::oppT(double t) const {
|
| return NULL;
|
| }
|
|
|
| -template<typename TCurve>
|
| -bool SkTSpan<TCurve>::removeAllBounded() {
|
| +template<typename TCurve, typename OppCurve>
|
| +bool SkTSpan<TCurve, OppCurve>::removeAllBounded() {
|
| bool deleteSpan = false;
|
| - SkTSpanBounded<TCurve>* bounded = fBounded;
|
| + SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
|
| while (bounded) {
|
| - SkTSpan* opp = bounded->fBounded;
|
| + SkTSpan<OppCurve, TCurve>* opp = bounded->fBounded;
|
| deleteSpan |= opp->removeBounded(this);
|
| bounded = bounded->fNext;
|
| }
|
| return deleteSpan;
|
| }
|
|
|
| -template<typename TCurve>
|
| -bool SkTSpan<TCurve>::removeBounded(const SkTSpan* opp) {
|
| +template<typename TCurve, typename OppCurve>
|
| +bool SkTSpan<TCurve, OppCurve>::removeBounded(const SkTSpan<OppCurve, TCurve>* opp) {
|
| if (fHasPerp) {
|
| bool foundStart = false;
|
| bool foundEnd = false;
|
| - SkTSpanBounded<TCurve>* bounded = fBounded;
|
| + SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
|
| while (bounded) {
|
| - SkTSpan* test = bounded->fBounded;
|
| + SkTSpan<OppCurve, TCurve>* test = bounded->fBounded;
|
| if (opp != test) {
|
| foundStart |= between(test->fStartT, fCoinStart.perpT(), test->fEndT);
|
| foundEnd |= between(test->fStartT, fCoinEnd.perpT(), test->fEndT);
|
| @@ -661,10 +700,10 @@ bool SkTSpan<TCurve>::removeBounded(const SkTSpan* opp) {
|
| fCoinEnd.init();
|
| }
|
| }
|
| - SkTSpanBounded<TCurve>* bounded = fBounded;
|
| - SkTSpanBounded<TCurve>* prev = NULL;
|
| + SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
|
| + SkTSpanBounded<OppCurve, TCurve>* prev = NULL;
|
| while (bounded) {
|
| - SkTSpanBounded<TCurve>* boundedNext = bounded->fNext;
|
| + SkTSpanBounded<OppCurve, TCurve>* boundedNext = bounded->fNext;
|
| if (opp == bounded->fBounded) {
|
| if (prev) {
|
| prev->fNext = boundedNext;
|
| @@ -681,8 +720,8 @@ bool SkTSpan<TCurve>::removeBounded(const SkTSpan* opp) {
|
| return false;
|
| }
|
|
|
| -template<typename TCurve>
|
| -bool SkTSpan<TCurve>::splitAt(SkTSpan* work, double t, SkChunkAlloc* heap) {
|
| +template<typename TCurve, typename OppCurve>
|
| +bool SkTSpan<TCurve, OppCurve>::splitAt(SkTSpan* work, double t, SkChunkAlloc* heap) {
|
| fStartT = t;
|
| fEndT = work->fEndT;
|
| if (fStartT == fEndT) {
|
| @@ -703,7 +742,7 @@ bool SkTSpan<TCurve>::splitAt(SkTSpan* work, double t, SkChunkAlloc* heap) {
|
| if (fNext) {
|
| fNext->fPrev = this;
|
| }
|
| - SkTSpanBounded<TCurve>* bounded = work->fBounded;
|
| + SkTSpanBounded<OppCurve, TCurve>* bounded = work->fBounded;
|
| fBounded = NULL;
|
| while (bounded) {
|
| this->addBounded(bounded->fBounded, heap);
|
| @@ -717,8 +756,8 @@ bool SkTSpan<TCurve>::splitAt(SkTSpan* work, double t, SkChunkAlloc* heap) {
|
| return true;
|
| }
|
|
|
| -template<typename TCurve>
|
| -void SkTSpan<TCurve>::validate() const {
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTSpan<TCurve, OppCurve>::validate() const {
|
| #if DEBUG_T_SECT
|
| SkASSERT(fNext == NULL || fNext != fPrev);
|
| SkASSERT(fNext == NULL || this == fNext->fPrev);
|
| @@ -743,12 +782,12 @@ void SkTSpan<TCurve>::validate() const {
|
| #endif
|
| }
|
|
|
| -template<typename TCurve>
|
| -void SkTSpan<TCurve>::validateBounded() const {
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTSpan<TCurve, OppCurve>::validateBounded() const {
|
| #if DEBUG_VALIDATE
|
| - const SkTSpanBounded<TCurve>* testBounded = fBounded;
|
| + const SkTSpanBounded<OppCurve, TCurve>* testBounded = fBounded;
|
| while (testBounded) {
|
| - const SkTSpan* overlap = testBounded->fBounded;
|
| + SkDEBUGCODE_(const SkTSpan<OppCurve, TCurve>* overlap = testBounded->fBounded);
|
| SkASSERT(!overlap->fDeleted);
|
| SkASSERT(((this->debugID() ^ overlap->debugID()) & 1) == 1);
|
| SkASSERT(overlap->findOppSpan(this));
|
| @@ -757,33 +796,29 @@ void SkTSpan<TCurve>::validateBounded() const {
|
| #endif
|
| }
|
|
|
| -template<typename TCurve>
|
| -void SkTSpan<TCurve>::validatePerpT(double oppT) const {
|
| -#if DEBUG_VALIDATE
|
| - const SkTSpanBounded<TCurve>* testBounded = fBounded;
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTSpan<TCurve, OppCurve>::validatePerpT(double oppT) const {
|
| + const SkTSpanBounded<OppCurve, TCurve>* testBounded = fBounded;
|
| while (testBounded) {
|
| - const SkTSpan* overlap = testBounded->fBounded;
|
| + const SkTSpan<OppCurve, TCurve>* overlap = testBounded->fBounded;
|
| if (between(overlap->fStartT, oppT, overlap->fEndT)) {
|
| return;
|
| }
|
| testBounded = testBounded->fNext;
|
| }
|
| SkASSERT(0);
|
| -#endif
|
| }
|
|
|
| -template<typename TCurve>
|
| -void SkTSpan<TCurve>::validatePerpPt(double t, const SkDPoint& pt) const {
|
| -#if DEBUG_T_SECT
|
| - PATH_OPS_DEBUG_CODE(SkASSERT(fDebugSect->fOppSect->fCurve.ptAtT(t) == pt));
|
| -#endif
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTSpan<TCurve, OppCurve>::validatePerpPt(double t, const SkDPoint& pt) const {
|
| + SkASSERT(fDebugSect->fOppSect->fCurve.ptAtT(t) == pt);
|
| }
|
|
|
|
|
| -template<typename TCurve>
|
| -SkTSect<TCurve>::SkTSect(const TCurve& c PATH_OPS_DEBUG_T_SECT_PARAMS(int id))
|
| +template<typename TCurve, typename OppCurve>
|
| +SkTSect<TCurve, OppCurve>::SkTSect(const TCurve& c PATH_OPS_DEBUG_T_SECT_PARAMS(int id))
|
| : fCurve(c)
|
| - , fHeap(sizeof(SkTSpan<TCurve>) * 4)
|
| + , fHeap(sizeof(SkTSpan<TCurve, OppCurve>) * 4)
|
| , fCoincident(NULL)
|
| , fDeleted(NULL)
|
| , fActiveCount(0)
|
| @@ -795,15 +830,16 @@ SkTSect<TCurve>::SkTSect(const TCurve& c PATH_OPS_DEBUG_T_SECT_PARAMS(int id))
|
| fHead->init(c);
|
| }
|
|
|
| -template<typename TCurve>
|
| -SkTSpan<TCurve>* SkTSect<TCurve>::addOne() {
|
| - SkTSpan<TCurve>* result;
|
| +template<typename TCurve, typename OppCurve>
|
| +SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::addOne() {
|
| + SkTSpan<TCurve, OppCurve>* result;
|
| if (fDeleted) {
|
| result = fDeleted;
|
| result->reset();
|
| fDeleted = result->fNext;
|
| } else {
|
| - result = SkNEW_PLACEMENT(fHeap.allocThrow(sizeof(SkTSpan<TCurve>)), SkTSpan<TCurve>);
|
| + result = SkNEW_PLACEMENT(fHeap.allocThrow(sizeof(SkTSpan<TCurve, OppCurve>)),
|
| + (SkTSpan<TCurve, OppCurve>));
|
| result->fBounded = NULL;
|
| #if DEBUG_T_SECT
|
| ++fDebugAllocatedCount;
|
| @@ -813,21 +849,21 @@ SkTSpan<TCurve>* SkTSect<TCurve>::addOne() {
|
| result->fDeleted = false;
|
| ++fActiveCount;
|
| PATH_OPS_DEBUG_T_SECT_CODE(result->fID = fDebugCount++ * 2 + fID);
|
| - PATH_OPS_DEBUG_CODE(result->fDebugSect = this);
|
| + SkDEBUGCODE(result->fDebugSect = this);
|
| return result;
|
| }
|
|
|
| -template<typename TCurve>
|
| -bool SkTSect<TCurve>::binarySearchCoin(SkTSect* sect2, double tStart, double tStep,
|
| - double* resultT, double* oppT) {
|
| - SkTSpan<TCurve> work;
|
| +template<typename TCurve, typename OppCurve>
|
| +bool SkTSect<TCurve, OppCurve>::binarySearchCoin(SkTSect<OppCurve, TCurve>* sect2, double tStart,
|
| + double tStep, double* resultT, double* oppT) {
|
| + SkTSpan<TCurve, OppCurve> work;
|
| double result = work.fStartT = work.fEndT = tStart;
|
| - PATH_OPS_DEBUG_CODE(work.fDebugSect = this);
|
| + SkDEBUGCODE(work.fDebugSect = this);
|
| SkDPoint last = fCurve.ptAtT(tStart);
|
| SkDPoint oppPt;
|
| bool flip = false;
|
| SkDEBUGCODE(bool down = tStep < 0);
|
| - const TCurve& opp = sect2->fCurve;
|
| + const OppCurve& opp = sect2->fCurve;
|
| do {
|
| tStep *= 0.5;
|
| work.fStartT += tStep;
|
| @@ -867,7 +903,7 @@ bool SkTSect<TCurve>::binarySearchCoin(SkTSect* sect2, double tStart, double tSt
|
| }
|
| if (oppPt.approximatelyEqual(opp[0])) {
|
| *oppT = 0;
|
| - } else if (oppPt.approximatelyEqual(opp[TCurve::kPointLast])) {
|
| + } else if (oppPt.approximatelyEqual(opp[OppCurve::kPointLast])) {
|
| *oppT = 1;
|
| }
|
| *resultT = result;
|
| @@ -877,25 +913,26 @@ bool SkTSect<TCurve>::binarySearchCoin(SkTSect* sect2, double tStart, double tSt
|
| // OPTIMIZE ? keep a sorted list of sizes in the form of a doubly-linked list in quad span
|
| // so that each quad sect has a pointer to the largest, and can update it as spans
|
| // are split
|
| -template<typename TCurve>
|
| -SkTSpan<TCurve>* SkTSect<TCurve>::boundsMax() const {
|
| - SkTSpan<TCurve>* test = fHead;
|
| - SkTSpan<TCurve>* largest = fHead;
|
| +template<typename TCurve, typename OppCurve>
|
| +SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::boundsMax() const {
|
| + SkTSpan<TCurve, OppCurve>* test = fHead;
|
| + SkTSpan<TCurve, OppCurve>* largest = fHead;
|
| bool lCollapsed = largest->fCollapsed;
|
| while ((test = test->fNext)) {
|
| bool tCollapsed = test->fCollapsed;
|
| if ((lCollapsed && !tCollapsed) || (lCollapsed == tCollapsed &&
|
| largest->fBoundsMax < test->fBoundsMax)) {
|
| largest = test;
|
| + lCollapsed = test->fCollapsed;
|
| }
|
| }
|
| return largest;
|
| }
|
|
|
| -template<typename TCurve>
|
| -void SkTSect<TCurve>::coincidentCheck(SkTSect* sect2) {
|
| - SkTSpan<TCurve>* first = fHead;
|
| - SkTSpan<TCurve>* last, * next;
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTSect<TCurve, OppCurve>::coincidentCheck(SkTSect<OppCurve, TCurve>* sect2) {
|
| + SkTSpan<TCurve, OppCurve>* first = fHead;
|
| + SkTSpan<TCurve, OppCurve>* last, * next;
|
| do {
|
| int consecutive = this->countConsecutiveSpans(first, &last);
|
| next = last->fNext;
|
| @@ -908,16 +945,16 @@ void SkTSect<TCurve>::coincidentCheck(SkTSect* sect2) {
|
| this->validate();
|
| sect2->validate();
|
| // check to see if a range of points are on the curve
|
| - SkTSpan<TCurve>* coinStart = first;
|
| + SkTSpan<TCurve, OppCurve>* coinStart = first;
|
| do {
|
| coinStart = this->extractCoincident(sect2, coinStart, last);
|
| } while (coinStart && !last->fDeleted);
|
| } while ((first = next));
|
| }
|
|
|
| -template<typename TCurve>
|
| -bool SkTSect<TCurve>::coincidentHasT(double t) {
|
| - SkTSpan<TCurve>* test = fCoincident;
|
| +template<typename TCurve, typename OppCurve>
|
| +bool SkTSect<TCurve, OppCurve>::coincidentHasT(double t) {
|
| + SkTSpan<TCurve, OppCurve>* test = fCoincident;
|
| while (test) {
|
| if (between(test->fStartT, t, test->fEndT)) {
|
| return true;
|
| @@ -927,12 +964,25 @@ bool SkTSect<TCurve>::coincidentHasT(double t) {
|
| return false;
|
| }
|
|
|
| -template<typename TCurve>
|
| -void SkTSect<TCurve>::computePerpendiculars(SkTSect* sect2, SkTSpan<TCurve>* first,
|
| - SkTSpan<TCurve>* last) {
|
| - const TCurve& opp = sect2->fCurve;
|
| - SkTSpan<TCurve>* work = first;
|
| - SkTSpan<TCurve>* prior = NULL;
|
| +template<typename TCurve, typename OppCurve>
|
| +int SkTSect<TCurve, OppCurve>::collapsed() const {
|
| + int result = 0;
|
| + const SkTSpan<TCurve, OppCurve>* test = fHead;
|
| + while (test) {
|
| + if (test->fCollapsed) {
|
| + ++result;
|
| + }
|
| + test = test->next();
|
| + }
|
| + return result;
|
| +}
|
| +
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTSect<TCurve, OppCurve>::computePerpendiculars(SkTSect<OppCurve, TCurve>* sect2,
|
| + SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last) {
|
| + const OppCurve& opp = sect2->fCurve;
|
| + SkTSpan<TCurve, OppCurve>* work = first;
|
| + SkTSpan<TCurve, OppCurve>* prior = NULL;
|
| do {
|
| if (!work->fHasPerp && !work->fCollapsed) {
|
| if (prior) {
|
| @@ -968,13 +1018,13 @@ void SkTSect<TCurve>::computePerpendiculars(SkTSect* sect2, SkTSpan<TCurve>* fir
|
| } while (true);
|
| }
|
|
|
| -template<typename TCurve>
|
| -int SkTSect<TCurve>::countConsecutiveSpans(SkTSpan<TCurve>* first,
|
| - SkTSpan<TCurve>** lastPtr) const {
|
| +template<typename TCurve, typename OppCurve>
|
| +int SkTSect<TCurve, OppCurve>::countConsecutiveSpans(SkTSpan<TCurve, OppCurve>* first,
|
| + SkTSpan<TCurve, OppCurve>** lastPtr) const {
|
| int consecutive = 1;
|
| - SkTSpan<TCurve>* last = first;
|
| + SkTSpan<TCurve, OppCurve>* last = first;
|
| do {
|
| - SkTSpan<TCurve>* next = last->fNext;
|
| + SkTSpan<TCurve, OppCurve>* next = last->fNext;
|
| if (!next) {
|
| break;
|
| }
|
| @@ -988,9 +1038,9 @@ int SkTSect<TCurve>::countConsecutiveSpans(SkTSpan<TCurve>* first,
|
| return consecutive;
|
| }
|
|
|
| -template<typename TCurve>
|
| -bool SkTSect<TCurve>::debugHasBounded(const SkTSpan<TCurve>* span) const {
|
| - const SkTSpan<TCurve>* test = fHead;
|
| +template<typename TCurve, typename OppCurve>
|
| +bool SkTSect<TCurve, OppCurve>::debugHasBounded(const SkTSpan<OppCurve, TCurve>* span) const {
|
| + const SkTSpan<TCurve, OppCurve>* test = fHead;
|
| if (!test) {
|
| return false;
|
| }
|
| @@ -1002,10 +1052,10 @@ bool SkTSect<TCurve>::debugHasBounded(const SkTSpan<TCurve>* span) const {
|
| return false;
|
| }
|
|
|
| -template<typename TCurve>
|
| -void SkTSect<TCurve>::deleteEmptySpans() {
|
| - SkTSpan<TCurve>* test;
|
| - SkTSpan<TCurve>* next = fHead;
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTSect<TCurve, OppCurve>::deleteEmptySpans() {
|
| + SkTSpan<TCurve, OppCurve>* test;
|
| + SkTSpan<TCurve, OppCurve>* next = fHead;
|
| while ((test = next)) {
|
| next = test->fNext;
|
| if (!test->fBounded) {
|
| @@ -1014,10 +1064,11 @@ void SkTSect<TCurve>::deleteEmptySpans() {
|
| }
|
| }
|
|
|
| -template<typename TCurve>
|
| -SkTSpan<TCurve>* SkTSect<TCurve>::extractCoincident(SkTSect* sect2, SkTSpan<TCurve>* first,
|
| - SkTSpan<TCurve>* last) {
|
| - first = findCoincidentRun(first, &last, sect2);
|
| +template<typename TCurve, typename OppCurve>
|
| +SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::extractCoincident(
|
| + SkTSect<OppCurve, TCurve>* sect2,
|
| + SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last) {
|
| + first = findCoincidentRun(first, &last);
|
| if (!first) {
|
| return NULL;
|
| }
|
| @@ -1025,24 +1076,25 @@ SkTSpan<TCurve>* SkTSect<TCurve>::extractCoincident(SkTSect* sect2, SkTSpan<TCur
|
| double startT = first->fStartT;
|
| double oppStartT SK_INIT_TO_AVOID_WARNING;
|
| double oppEndT SK_INIT_TO_AVOID_WARNING;
|
| - SkTSpan<TCurve>* prev = first->fPrev;
|
| + SkTSpan<TCurve, OppCurve>* prev = first->fPrev;
|
| SkASSERT(first->fCoinStart.isCoincident());
|
| - SkTSpan<TCurve>* oppFirst = first->findOppT(first->fCoinStart.perpT());
|
| + SkTSpan<OppCurve, TCurve>* oppFirst = first->findOppT(first->fCoinStart.perpT());
|
| SkASSERT(last->fCoinEnd.isCoincident());
|
| bool oppMatched = first->fCoinStart.perpT() < first->fCoinEnd.perpT();
|
| double coinStart;
|
| SkDEBUGCODE(double coinEnd);
|
| + SkTSpan<OppCurve, TCurve>* cutFirst;
|
| if (prev && prev->fEndT == startT
|
| && this->binarySearchCoin(sect2, startT, prev->fStartT - startT, &coinStart,
|
| &oppStartT)
|
| - && prev->fStartT < coinStart && coinStart < startT) {
|
| - oppFirst = prev->findOppT(oppStartT); // find opp start before splitting prev
|
| - SkASSERT(oppFirst);
|
| + && prev->fStartT < coinStart && coinStart < startT
|
| + && (cutFirst = prev->oppT(oppStartT))) {
|
| + oppFirst = cutFirst;
|
| first = this->addSplitAt(prev, coinStart);
|
| first->markCoincident();
|
| prev->fCoinEnd.markCoincident();
|
| if (oppFirst->fStartT < oppStartT && oppStartT < oppFirst->fEndT) {
|
| - SkTSpan<TCurve>* oppHalf = sect2->addSplitAt(oppFirst, oppStartT);
|
| + SkTSpan<OppCurve, TCurve>* oppHalf = sect2->addSplitAt(oppFirst, oppStartT);
|
| if (oppMatched) {
|
| oppFirst->fCoinEnd.markCoincident();
|
| oppHalf->markCoincident();
|
| @@ -1056,7 +1108,8 @@ SkTSpan<TCurve>* SkTSect<TCurve>::extractCoincident(SkTSect* sect2, SkTSpan<TCur
|
| SkDEBUGCODE(coinStart = first->fStartT);
|
| SkDEBUGCODE(oppStartT = oppMatched ? oppFirst->fStartT : oppFirst->fEndT);
|
| }
|
| - SkTSpan<TCurve>* oppLast;
|
| + // FIXME: incomplete : if we're not at the end, find end of coin
|
| + SkTSpan<OppCurve, TCurve>* oppLast;
|
| SkASSERT(last->fCoinEnd.isCoincident());
|
| oppLast = last->findOppT(last->fCoinEnd.perpT());
|
| SkDEBUGCODE(coinEnd = last->fEndT);
|
| @@ -1073,8 +1126,8 @@ SkTSpan<TCurve>* SkTSect<TCurve>::extractCoincident(SkTSect* sect2, SkTSpan<TCur
|
| // reduce coincident runs to single entries
|
| this->validate();
|
| sect2->validate();
|
| - bool deleteThisSpan = this->updateBounded(first, last, oppFirst);
|
| - bool deleteSect2Span = sect2->updateBounded(oppFirst, oppLast, first);
|
| + bool deleteEmptySpans = this->updateBounded(first, last, oppFirst);
|
| + deleteEmptySpans |= sect2->updateBounded(oppFirst, oppLast, first);
|
| this->removeSpanRange(first, last);
|
| sect2->removeSpanRange(oppFirst, oppLast);
|
| first->fEndT = last->fEndT;
|
| @@ -1096,10 +1149,8 @@ SkTSpan<TCurve>* SkTSect<TCurve>::extractCoincident(SkTSect* sect2, SkTSpan<TCur
|
| last = first->fNext;
|
| this->removeCoincident(first, false);
|
| sect2->removeCoincident(oppFirst, true);
|
| - if (deleteThisSpan) {
|
| + if (deleteEmptySpans) {
|
| this->deleteEmptySpans();
|
| - }
|
| - if (deleteSect2Span) {
|
| sect2->deleteEmptySpans();
|
| }
|
| this->validate();
|
| @@ -1107,17 +1158,19 @@ SkTSpan<TCurve>* SkTSect<TCurve>::extractCoincident(SkTSect* sect2, SkTSpan<TCur
|
| return last && !last->fDeleted ? last : NULL;
|
| }
|
|
|
| -template<typename TCurve>
|
| -SkTSpan<TCurve>* SkTSect<TCurve>::findCoincidentRun(SkTSpan<TCurve>* first,
|
| - SkTSpan<TCurve>** lastPtr, const SkTSect* sect2) {
|
| - SkTSpan<TCurve>* work = first;
|
| - SkTSpan<TCurve>* lastCandidate = NULL;
|
| +template<typename TCurve, typename OppCurve>
|
| +SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::findCoincidentRun(
|
| + SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>** lastPtr) {
|
| + SkTSpan<TCurve, OppCurve>* work = first;
|
| + SkTSpan<TCurve, OppCurve>* lastCandidate = NULL;
|
| first = NULL;
|
| // find the first fully coincident span
|
| do {
|
| if (work->fCoinStart.isCoincident()) {
|
| +#if DEBUG_T_SECT
|
| work->validatePerpT(work->fCoinStart.perpT());
|
| work->validatePerpPt(work->fCoinStart.perpT(), work->fCoinStart.perpPt());
|
| +#endif
|
| SkASSERT(work->hasOppT(work->fCoinStart.perpT()));
|
| if (!work->fCoinEnd.isCoincident()) {
|
| break;
|
| @@ -1126,6 +1179,9 @@ SkTSpan<TCurve>* SkTSect<TCurve>::findCoincidentRun(SkTSpan<TCurve>* first,
|
| if (!first) {
|
| first = work;
|
| }
|
| + } else if (first && work->fCollapsed) {
|
| + *lastPtr = lastCandidate;
|
| + return first;
|
| } else {
|
| lastCandidate = NULL;
|
| SkASSERT(!first);
|
| @@ -1142,9 +1198,10 @@ SkTSpan<TCurve>* SkTSect<TCurve>::findCoincidentRun(SkTSpan<TCurve>* first,
|
| return first;
|
| }
|
|
|
| -template<typename TCurve>
|
| -int SkTSect<TCurve>::intersects(SkTSpan<TCurve>* span, const SkTSect* opp,
|
| - SkTSpan<TCurve>* oppSpan, int* oppResult) const {
|
| +template<typename TCurve, typename OppCurve>
|
| +int SkTSect<TCurve, OppCurve>::intersects(SkTSpan<TCurve, OppCurve>* span,
|
| + SkTSect<OppCurve, TCurve>* opp,
|
| + SkTSpan<OppCurve, TCurve>* oppSpan, int* oppResult) {
|
| bool spanStart, oppStart;
|
| int hullResult = span->hullsIntersect(oppSpan, &spanStart, &oppStart);
|
| if (hullResult >= 0) {
|
| @@ -1194,21 +1251,22 @@ int SkTSect<TCurve>::intersects(SkTSpan<TCurve>* span, const SkTSect* opp,
|
| // while the intersection points are sufficiently far apart:
|
| // construct the tangent lines from the intersections
|
| // find the point where the tangent line intersects the opposite curve
|
| -template<typename TCurve>
|
| -int SkTSect<TCurve>::linesIntersect(const SkTSpan<TCurve>* span, const SkTSect* opp,
|
| - const SkTSpan<TCurve>* oppSpan, SkIntersections* i) const {
|
| +template<typename TCurve, typename OppCurve>
|
| +int SkTSect<TCurve, OppCurve>::linesIntersect(SkTSpan<TCurve, OppCurve>* span,
|
| + SkTSect<OppCurve, TCurve>* opp,
|
| + SkTSpan<OppCurve, TCurve>* oppSpan, SkIntersections* i) {
|
| SkIntersections thisRayI, oppRayI;
|
| SkDLine thisLine = {{ span->fPart[0], span->fPart[TCurve::kPointLast] }};
|
| - SkDLine oppLine = {{ oppSpan->fPart[0], oppSpan->fPart[TCurve::kPointLast] }};
|
| + SkDLine oppLine = {{ oppSpan->fPart[0], oppSpan->fPart[OppCurve::kPointLast] }};
|
| int loopCount = 0;
|
| double bestDistSq = DBL_MAX;
|
| + if (!thisRayI.intersectRay(opp->fCurve, thisLine)) {
|
| + return 0;
|
| + }
|
| + if (!oppRayI.intersectRay(this->fCurve, oppLine)) {
|
| + return 0;
|
| + }
|
| do {
|
| - if (!thisRayI.intersectRay(opp->fCurve, thisLine)) {
|
| - return 0;
|
| - }
|
| - if (!oppRayI.intersectRay(this->fCurve, oppLine)) {
|
| - return 0;
|
| - }
|
| // pick the closest pair of points
|
| double closest = DBL_MAX;
|
| int closeIndex SK_INIT_TO_AVOID_WARNING;
|
| @@ -1230,7 +1288,7 @@ int SkTSect<TCurve>::linesIntersect(const SkTSpan<TCurve>* span, const SkTSect*
|
| }
|
| }
|
| if (closest == DBL_MAX) {
|
| - return 0;
|
| + break;
|
| }
|
| const SkDPoint& oppIPt = thisRayI.pt(oppCloseIndex);
|
| const SkDPoint& iPt = oppRayI.pt(closeIndex);
|
| @@ -1242,20 +1300,88 @@ int SkTSect<TCurve>::linesIntersect(const SkTSpan<TCurve>* span, const SkTSect*
|
| }
|
| double distSq = oppIPt.distanceSquared(iPt);
|
| if (bestDistSq < distSq || ++loopCount > 5) {
|
| - break;
|
| + return 0;
|
| }
|
| bestDistSq = distSq;
|
| - thisLine[0] = fCurve.ptAtT(oppRayI[0][closeIndex]);
|
| - thisLine[1] = thisLine[0] + fCurve.dxdyAtT(oppRayI[0][closeIndex]);
|
| - oppLine[0] = opp->fCurve.ptAtT(thisRayI[0][oppCloseIndex]);
|
| - oppLine[1] = oppLine[0] + opp->fCurve.dxdyAtT(thisRayI[0][oppCloseIndex]);
|
| + double oppStart = oppRayI[0][closeIndex];
|
| + thisLine[0] = fCurve.ptAtT(oppStart);
|
| + thisLine[1] = thisLine[0] + fCurve.dxdyAtT(oppStart);
|
| + if (!thisRayI.intersectRay(opp->fCurve, thisLine)) {
|
| + break;
|
| + }
|
| + double start = thisRayI[0][oppCloseIndex];
|
| + oppLine[0] = opp->fCurve.ptAtT(start);
|
| + oppLine[1] = oppLine[0] + opp->fCurve.dxdyAtT(start);
|
| + if (!oppRayI.intersectRay(this->fCurve, oppLine)) {
|
| + break;
|
| + }
|
| } while (true);
|
| - return false;
|
| + // convergence may fail if the curves are nearly coincident
|
| + SkTCoincident<OppCurve, TCurve> oCoinS, oCoinE;
|
| + oCoinS.setPerp(opp->fCurve, oppSpan->fStartT, oppSpan->fPart[0], fCurve);
|
| + oCoinE.setPerp(opp->fCurve, oppSpan->fEndT, oppSpan->fPart[OppCurve::kPointLast], fCurve);
|
| + double tStart = oCoinS.perpT();
|
| + double tEnd = oCoinE.perpT();
|
| + bool swap = tStart > tEnd;
|
| + if (swap) {
|
| + SkTSwap(tStart, tEnd);
|
| + }
|
| + tStart = SkTMax(tStart, span->fStartT);
|
| + tEnd = SkTMin(tEnd, span->fEndT);
|
| + if (tStart > tEnd) {
|
| + return 0;
|
| + }
|
| + SkDVector perpS, perpE;
|
| + if (tStart == span->fStartT) {
|
| + SkTCoincident<TCurve, OppCurve> coinS;
|
| + coinS.setPerp(fCurve, span->fStartT, span->fPart[0], opp->fCurve);
|
| + perpS = span->fPart[0] - coinS.perpPt();
|
| + } else if (swap) {
|
| + perpS = oCoinE.perpPt() - oppSpan->fPart[OppCurve::kPointLast];
|
| + } else {
|
| + perpS = oCoinS.perpPt() - oppSpan->fPart[0];
|
| + }
|
| + if (tEnd == span->fEndT) {
|
| + SkTCoincident<TCurve, OppCurve> coinE;
|
| + coinE.setPerp(fCurve, span->fEndT, span->fPart[TCurve::kPointLast], opp->fCurve);
|
| + perpE = span->fPart[TCurve::kPointLast] - coinE.perpPt();
|
| + } else if (swap) {
|
| + perpE = oCoinS.perpPt() - oppSpan->fPart[0];
|
| + } else {
|
| + perpE = oCoinE.perpPt() - oppSpan->fPart[OppCurve::kPointLast];
|
| + }
|
| + if (perpS.dot(perpE) >= 0) {
|
| + return 0;
|
| + }
|
| + SkTCoincident<TCurve, OppCurve> coinW;
|
| + double workT = tStart;
|
| + double tStep = tEnd - tStart;
|
| + SkDPoint workPt;
|
| + do {
|
| + tStep *= 0.5;
|
| + if (precisely_zero(tStep)) {
|
| + return 0;
|
| + }
|
| + workT += tStep;
|
| + workPt = fCurve.ptAtT(workT);
|
| + coinW.setPerp(fCurve, workT, workPt, opp->fCurve);
|
| + SkDVector perpW = workPt - coinW.perpPt();
|
| + if ((perpS.dot(perpW) >= 0) == (tStep < 0)) {
|
| + tStep = -tStep;
|
| + }
|
| + } while (!workPt.approximatelyEqual(coinW.perpPt()));
|
| + double oppTTest = coinW.perpT();
|
| + if (!opp->fHead->contains(oppTTest)) {
|
| + return 0;
|
| + }
|
| + i->setMax(1);
|
| + i->insert(workT, oppTTest, workPt);
|
| + return 1;
|
| }
|
|
|
|
|
| -template<typename TCurve>
|
| -void SkTSect<TCurve>::markSpanGone(SkTSpan<TCurve>* span) {
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTSect<TCurve, OppCurve>::markSpanGone(SkTSpan<TCurve, OppCurve>* span) {
|
| --fActiveCount;
|
| span->fNext = fDeleted;
|
| fDeleted = span;
|
| @@ -1263,16 +1389,17 @@ void SkTSect<TCurve>::markSpanGone(SkTSpan<TCurve>* span) {
|
| span->fDeleted = true;
|
| }
|
|
|
| -template<typename TCurve>
|
| -bool SkTSect<TCurve>::matchedDirection(double t, const SkTSect* sect2, double t2) const {
|
| +template<typename TCurve, typename OppCurve>
|
| +bool SkTSect<TCurve, OppCurve>::matchedDirection(double t, const SkTSect<OppCurve, TCurve>* sect2,
|
| + double t2) const {
|
| SkDVector dxdy = this->fCurve.dxdyAtT(t);
|
| SkDVector dxdy2 = sect2->fCurve.dxdyAtT(t2);
|
| return dxdy.dot(dxdy2) >= 0;
|
| }
|
|
|
| -template<typename TCurve>
|
| -void SkTSect<TCurve>::matchedDirCheck(double t, const SkTSect* sect2, double t2,
|
| - bool* calcMatched, bool* oppMatched) const {
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTSect<TCurve, OppCurve>::matchedDirCheck(double t, const SkTSect<OppCurve, TCurve>* sect2,
|
| + double t2, bool* calcMatched, bool* oppMatched) const {
|
| if (*calcMatched) {
|
| SkASSERT(*oppMatched == this->matchedDirection(t, sect2, t2));
|
| } else {
|
| @@ -1281,13 +1408,13 @@ void SkTSect<TCurve>::matchedDirCheck(double t, const SkTSect* sect2, double t2,
|
| }
|
| }
|
|
|
| -template<typename TCurve>
|
| -void SkTSect<TCurve>::mergeCoincidence(SkTSect* sect2) {
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTSect<TCurve, OppCurve>::mergeCoincidence(SkTSect<OppCurve, TCurve>* sect2) {
|
| double smallLimit = 0;
|
| do {
|
| // find the smallest unprocessed span
|
| - SkTSpan<TCurve>* smaller = NULL;
|
| - SkTSpan<TCurve>* test = fCoincident;
|
| + SkTSpan<TCurve, OppCurve>* smaller = NULL;
|
| + SkTSpan<TCurve, OppCurve>* test = fCoincident;
|
| do {
|
| if (test->fStartT < smallLimit) {
|
| continue;
|
| @@ -1302,9 +1429,9 @@ void SkTSect<TCurve>::mergeCoincidence(SkTSect* sect2) {
|
| }
|
| smallLimit = smaller->fEndT;
|
| // find next larger span
|
| - SkTSpan<TCurve>* prior = NULL;
|
| - SkTSpan<TCurve>* larger = NULL;
|
| - SkTSpan<TCurve>* largerPrior = NULL;
|
| + SkTSpan<TCurve, OppCurve>* prior = NULL;
|
| + SkTSpan<TCurve, OppCurve>* larger = NULL;
|
| + SkTSpan<TCurve, OppCurve>* largerPrior = NULL;
|
| test = fCoincident;
|
| do {
|
| if (test->fStartT < smaller->fEndT) {
|
| @@ -1323,7 +1450,7 @@ void SkTSect<TCurve>::mergeCoincidence(SkTSect* sect2) {
|
| // check middle t value to see if it is coincident as well
|
| double midT = (smaller->fEndT + larger->fStartT) / 2;
|
| SkDPoint midPt = fCurve.ptAtT(midT);
|
| - SkTCoincident<TCurve> coin;
|
| + SkTCoincident<TCurve, OppCurve> coin;
|
| coin.setPerp(fCurve, midT, midPt, sect2->fCurve);
|
| if (coin.isCoincident()) {
|
| smaller->fEndT = larger->fEndT;
|
| @@ -1337,10 +1464,11 @@ void SkTSect<TCurve>::mergeCoincidence(SkTSect* sect2) {
|
| } while (true);
|
| }
|
|
|
| -template<typename TCurve>
|
| -SkTSpan<TCurve>* SkTSect<TCurve>::prev(SkTSpan<TCurve>* span) const {
|
| - SkTSpan<TCurve>* result = NULL;
|
| - SkTSpan<TCurve>* test = fHead;
|
| +template<typename TCurve, typename OppCurve>
|
| +SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::prev(
|
| + SkTSpan<TCurve, OppCurve>* span) const {
|
| + SkTSpan<TCurve, OppCurve>* result = NULL;
|
| + SkTSpan<TCurve, OppCurve>* test = fHead;
|
| while (span != test) {
|
| result = test;
|
| test = test->fNext;
|
| @@ -1349,13 +1477,13 @@ SkTSpan<TCurve>* SkTSect<TCurve>::prev(SkTSpan<TCurve>* span) const {
|
| return result;
|
| }
|
|
|
| -template<typename TCurve>
|
| -void SkTSect<TCurve>::recoverCollapsed() {
|
| - SkTSpan<TCurve>* deleted = fDeleted;
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTSect<TCurve, OppCurve>::recoverCollapsed() {
|
| + SkTSpan<TCurve, OppCurve>* deleted = fDeleted;
|
| while (deleted) {
|
| - SkTSpan<TCurve>* delNext = deleted->fNext;
|
| + SkTSpan<TCurve, OppCurve>* delNext = deleted->fNext;
|
| if (deleted->fCollapsed) {
|
| - SkTSpan<TCurve>** spanPtr = &fHead;
|
| + SkTSpan<TCurve, OppCurve>** spanPtr = &fHead;
|
| while (*spanPtr && (*spanPtr)->fEndT <= deleted->fStartT) {
|
| spanPtr = &(*spanPtr)->fNext;
|
| }
|
| @@ -1366,13 +1494,13 @@ void SkTSect<TCurve>::recoverCollapsed() {
|
| }
|
| }
|
|
|
| -template<typename TCurve>
|
| -void SkTSect<TCurve>::removeAllBut(const SkTSpan<TCurve>* keep, SkTSpan<TCurve>* span,
|
| - SkTSect* opp) {
|
| - const SkTSpanBounded<TCurve>* testBounded = span->fBounded;
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTSect<TCurve, OppCurve>::removeAllBut(const SkTSpan<OppCurve, TCurve>* keep,
|
| + SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp) {
|
| + const SkTSpanBounded<OppCurve, TCurve>* testBounded = span->fBounded;
|
| while (testBounded) {
|
| - SkTSpan<TCurve>* bounded = testBounded->fBounded;
|
| - const SkTSpanBounded<TCurve>* next = testBounded->fNext;
|
| + SkTSpan<OppCurve, TCurve>* bounded = testBounded->fBounded;
|
| + const SkTSpanBounded<OppCurve, TCurve>* next = testBounded->fNext;
|
| // may have been deleted when opp did 'remove all but'
|
| if (bounded != keep && !bounded->fDeleted) {
|
| SkAssertResult(SkDEBUGCODE(!) span->removeBounded(bounded));
|
| @@ -1387,10 +1515,10 @@ void SkTSect<TCurve>::removeAllBut(const SkTSpan<TCurve>* keep, SkTSpan<TCurve>*
|
| SkASSERT(keep->findOppSpan(span));
|
| }
|
|
|
| -template<typename TCurve>
|
| -void SkTSect<TCurve>::removeByPerpendicular(SkTSect<TCurve>* opp) {
|
| - SkTSpan<TCurve>* test = fHead;
|
| - SkTSpan<TCurve>* next;
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTSect<TCurve, OppCurve>::removeByPerpendicular(SkTSect<OppCurve, TCurve>* opp) {
|
| + SkTSpan<TCurve, OppCurve>* test = fHead;
|
| + SkTSpan<TCurve, OppCurve>* next;
|
| do {
|
| next = test->fNext;
|
| if (test->fCoinStart.perpT() < 0 || test->fCoinEnd.perpT() < 0) {
|
| @@ -1409,8 +1537,8 @@ void SkTSect<TCurve>::removeByPerpendicular(SkTSect<TCurve>* opp) {
|
| } while ((test = next));
|
| }
|
|
|
| -template<typename TCurve>
|
| -void SkTSect<TCurve>::removeCoincident(SkTSpan<TCurve>* span, bool isBetween) {
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTSect<TCurve, OppCurve>::removeCoincident(SkTSpan<TCurve, OppCurve>* span, bool isBetween) {
|
| this->unlinkSpan(span);
|
| if (isBetween || between(0, span->fCoinStart.perpT(), 1)) {
|
| --fActiveCount;
|
| @@ -1421,21 +1549,22 @@ void SkTSect<TCurve>::removeCoincident(SkTSpan<TCurve>* span, bool isBetween) {
|
| }
|
| }
|
|
|
| -template<typename TCurve>
|
| -void SkTSect<TCurve>::removeSpan(SkTSpan<TCurve>* span) {
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTSect<TCurve, OppCurve>::removeSpan(SkTSpan<TCurve, OppCurve>* span) {
|
| this->unlinkSpan(span);
|
| this->markSpanGone(span);
|
| }
|
|
|
| -template<typename TCurve>
|
| -void SkTSect<TCurve>::removeSpanRange(SkTSpan<TCurve>* first, SkTSpan<TCurve>* last) {
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTSect<TCurve, OppCurve>::removeSpanRange(SkTSpan<TCurve, OppCurve>* first,
|
| + SkTSpan<TCurve, OppCurve>* last) {
|
| if (first == last) {
|
| return;
|
| }
|
| - SkTSpan<TCurve>* span = first;
|
| + SkTSpan<TCurve, OppCurve>* span = first;
|
| SkASSERT(span);
|
| - SkTSpan<TCurve>* final = last->fNext;
|
| - SkTSpan<TCurve>* next = span->fNext;
|
| + SkTSpan<TCurve, OppCurve>* final = last->fNext;
|
| + SkTSpan<TCurve, OppCurve>* next = span->fNext;
|
| while ((span = next) && span != final) {
|
| next = span->fNext;
|
| this->markSpanGone(span);
|
| @@ -1446,12 +1575,13 @@ void SkTSect<TCurve>::removeSpanRange(SkTSpan<TCurve>* first, SkTSpan<TCurve>* l
|
| first->fNext = final;
|
| }
|
|
|
| -template<typename TCurve>
|
| -void SkTSect<TCurve>::removeSpans(SkTSpan<TCurve>* span, SkTSect<TCurve>* opp) {
|
| - SkTSpanBounded<TCurve>* bounded = span->fBounded;
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTSect<TCurve, OppCurve>::removeSpans(SkTSpan<TCurve, OppCurve>* span,
|
| + SkTSect<OppCurve, TCurve>* opp) {
|
| + SkTSpanBounded<OppCurve, TCurve>* bounded = span->fBounded;
|
| while (bounded) {
|
| - SkTSpan<TCurve>* spanBounded = bounded->fBounded;
|
| - SkTSpanBounded<TCurve>* next = bounded->fNext;
|
| + SkTSpan<OppCurve, TCurve>* spanBounded = bounded->fBounded;
|
| + SkTSpanBounded<OppCurve, TCurve>* next = bounded->fNext;
|
| if (span->removeBounded(spanBounded)) { // shuffles last into position 0
|
| this->removeSpan(span);
|
| }
|
| @@ -1463,10 +1593,11 @@ void SkTSect<TCurve>::removeSpans(SkTSpan<TCurve>* span, SkTSect<TCurve>* opp) {
|
| }
|
| }
|
|
|
| -template<typename TCurve>
|
| -SkTSpan<TCurve>* SkTSect<TCurve>::spanAtT(double t, SkTSpan<TCurve>** priorSpan) {
|
| - SkTSpan<TCurve>* test = fHead;
|
| - SkTSpan<TCurve>* prev = NULL;
|
| +template<typename TCurve, typename OppCurve>
|
| +SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::spanAtT(double t,
|
| + SkTSpan<TCurve, OppCurve>** priorSpan) {
|
| + SkTSpan<TCurve, OppCurve>* test = fHead;
|
| + SkTSpan<TCurve, OppCurve>* prev = NULL;
|
| while (test && test->fEndT < t) {
|
| prev = test;
|
| test = test->fNext;
|
| @@ -1475,10 +1606,10 @@ SkTSpan<TCurve>* SkTSect<TCurve>::spanAtT(double t, SkTSpan<TCurve>** priorSpan)
|
| return test && test->fStartT <= t ? test : NULL;
|
| }
|
|
|
| -template<typename TCurve>
|
| -SkTSpan<TCurve>* SkTSect<TCurve>::tail() {
|
| - SkTSpan<TCurve>* result = fHead;
|
| - SkTSpan<TCurve>* next = fHead;
|
| +template<typename TCurve, typename OppCurve>
|
| +SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::tail() {
|
| + SkTSpan<TCurve, OppCurve>* result = fHead;
|
| + SkTSpan<TCurve, OppCurve>* next = fHead;
|
| while ((next = next->fNext)) {
|
| if (next->fEndT > result->fEndT) {
|
| result = next;
|
| @@ -1489,13 +1620,14 @@ SkTSpan<TCurve>* SkTSect<TCurve>::tail() {
|
|
|
| /* Each span has a range of opposite spans it intersects. After the span is split in two,
|
| adjust the range to its new size */
|
| -template<typename TCurve>
|
| -void SkTSect<TCurve>::trim(SkTSpan<TCurve>* span, SkTSect* opp) {
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTSect<TCurve, OppCurve>::trim(SkTSpan<TCurve, OppCurve>* span,
|
| + SkTSect<OppCurve, TCurve>* opp) {
|
| span->initBounds(fCurve);
|
| - const SkTSpanBounded<TCurve>* testBounded = span->fBounded;
|
| + const SkTSpanBounded<OppCurve, TCurve>* testBounded = span->fBounded;
|
| while (testBounded) {
|
| - SkTSpan<TCurve>* test = testBounded->fBounded;
|
| - const SkTSpanBounded<TCurve>* next = testBounded->fNext;
|
| + SkTSpan<OppCurve, TCurve>* test = testBounded->fBounded;
|
| + const SkTSpanBounded<OppCurve, TCurve>* next = testBounded->fNext;
|
| int oppSects, sects = this->intersects(span, opp, test, &oppSects);
|
| if (sects >= 1) {
|
| if (oppSects == 2) {
|
| @@ -1519,10 +1651,10 @@ void SkTSect<TCurve>::trim(SkTSpan<TCurve>* span, SkTSect* opp) {
|
| }
|
| }
|
|
|
| -template<typename TCurve>
|
| -void SkTSect<TCurve>::unlinkSpan(SkTSpan<TCurve>* span) {
|
| - SkTSpan<TCurve>* prev = span->fPrev;
|
| - SkTSpan<TCurve>* next = span->fNext;
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTSect<TCurve, OppCurve>::unlinkSpan(SkTSpan<TCurve, OppCurve>* span) {
|
| + SkTSpan<TCurve, OppCurve>* prev = span->fPrev;
|
| + SkTSpan<TCurve, OppCurve>* next = span->fNext;
|
| if (prev) {
|
| prev->fNext = next;
|
| if (next) {
|
| @@ -1536,11 +1668,11 @@ void SkTSect<TCurve>::unlinkSpan(SkTSpan<TCurve>* span) {
|
| }
|
| }
|
|
|
| -template<typename TCurve>
|
| -bool SkTSect<TCurve>::updateBounded(SkTSpan<TCurve>* first, SkTSpan<TCurve>* last,
|
| - SkTSpan<TCurve>* oppFirst) {
|
| - SkTSpan<TCurve>* test = first;
|
| - const SkTSpan<TCurve>* final = last->next();
|
| +template<typename TCurve, typename OppCurve>
|
| +bool SkTSect<TCurve, OppCurve>::updateBounded(SkTSpan<TCurve, OppCurve>* first,
|
| + SkTSpan<TCurve, OppCurve>* last, SkTSpan<OppCurve, TCurve>* oppFirst) {
|
| + SkTSpan<TCurve, OppCurve>* test = first;
|
| + const SkTSpan<TCurve, OppCurve>* final = last->next();
|
| bool deleteSpan = false;
|
| do {
|
| deleteSpan |= test->removeAllBounded();
|
| @@ -1552,12 +1684,12 @@ bool SkTSect<TCurve>::updateBounded(SkTSpan<TCurve>* first, SkTSpan<TCurve>* las
|
| }
|
|
|
|
|
| -template<typename TCurve>
|
| -void SkTSect<TCurve>::validate() const {
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTSect<TCurve, OppCurve>::validate() const {
|
| #if DEBUG_T_SECT
|
| int count = 0;
|
| if (fHead) {
|
| - const SkTSpan<TCurve>* span = fHead;
|
| + const SkTSpan<TCurve, OppCurve>* span = fHead;
|
| SkASSERT(!span->fPrev);
|
| SkDEBUGCODE(double last = 0);
|
| do {
|
| @@ -1570,12 +1702,12 @@ void SkTSect<TCurve>::validate() const {
|
| SkASSERT(count == fActiveCount);
|
| SkASSERT(fActiveCount <= fDebugAllocatedCount);
|
| int deletedCount = 0;
|
| - const SkTSpan<TCurve>* deleted = fDeleted;
|
| + const SkTSpan<TCurve, OppCurve>* deleted = fDeleted;
|
| while (deleted) {
|
| ++deletedCount;
|
| deleted = deleted->fNext;
|
| }
|
| - const SkTSpan<TCurve>* coincident = fCoincident;
|
| + const SkTSpan<TCurve, OppCurve>* coincident = fCoincident;
|
| while (coincident) {
|
| ++deletedCount;
|
| coincident = coincident->fNext;
|
| @@ -1584,28 +1716,28 @@ void SkTSect<TCurve>::validate() const {
|
| #endif
|
| }
|
|
|
| -template<typename TCurve>
|
| -void SkTSect<TCurve>::validateBounded() const {
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTSect<TCurve, OppCurve>::validateBounded() const {
|
| #if DEBUG_T_SECT
|
| if (!fHead) {
|
| return;
|
| }
|
| - const SkTSpan<TCurve>* span = fHead;
|
| + const SkTSpan<TCurve, OppCurve>* span = fHead;
|
| do {
|
| span->validateBounded();
|
| } while ((span = span->fNext) != NULL);
|
| #endif
|
| }
|
|
|
| -template<typename TCurve>
|
| -int SkTSect<TCurve>::EndsEqual(const SkTSect* sect1, const SkTSect* sect2,
|
| - SkIntersections* intersections) {
|
| +template<typename TCurve, typename OppCurve>
|
| +int SkTSect<TCurve, OppCurve>::EndsEqual(const SkTSect<TCurve, OppCurve>* sect1,
|
| + const SkTSect<OppCurve, TCurve>* sect2, SkIntersections* intersections) {
|
| int zeroOneSet = 0;
|
| if (sect1->fCurve[0] == sect2->fCurve[0]) {
|
| zeroOneSet |= kZeroS1Set | kZeroS2Set;
|
| intersections->insert(0, 0, sect1->fCurve[0]);
|
| }
|
| - if (sect1->fCurve[0] == sect2->fCurve[TCurve::kPointLast]) {
|
| + if (sect1->fCurve[0] == sect2->fCurve[OppCurve::kPointLast]) {
|
| zeroOneSet |= kZeroS1Set | kOneS2Set;
|
| intersections->insert(0, 1, sect1->fCurve[0]);
|
| }
|
| @@ -1613,7 +1745,7 @@ int SkTSect<TCurve>::EndsEqual(const SkTSect* sect1, const SkTSect* sect2,
|
| zeroOneSet |= kOneS1Set | kZeroS2Set;
|
| intersections->insert(1, 0, sect1->fCurve[TCurve::kPointLast]);
|
| }
|
| - if (sect1->fCurve[TCurve::kPointLast] == sect2->fCurve[TCurve::kPointLast]) {
|
| + if (sect1->fCurve[TCurve::kPointLast] == sect2->fCurve[OppCurve::kPointLast]) {
|
| zeroOneSet |= kOneS1Set | kOneS2Set;
|
| intersections->insert(1, 1, sect1->fCurve[TCurve::kPointLast]);
|
| }
|
| @@ -1624,9 +1756,9 @@ int SkTSect<TCurve>::EndsEqual(const SkTSect* sect1, const SkTSect* sect2,
|
| intersections->insertNear(0, 0, sect1->fCurve[0], sect2->fCurve[0]);
|
| }
|
| if (!(zeroOneSet & (kZeroS1Set | kOneS2Set))
|
| - && sect1->fCurve[0].approximatelyEqual(sect2->fCurve[TCurve::kPointLast])) {
|
| + && sect1->fCurve[0].approximatelyEqual(sect2->fCurve[OppCurve::kPointLast])) {
|
| zeroOneSet |= kZeroS1Set | kOneS2Set;
|
| - intersections->insertNear(0, 1, sect1->fCurve[0], sect2->fCurve[TCurve::kPointLast]);
|
| + intersections->insertNear(0, 1, sect1->fCurve[0], sect2->fCurve[OppCurve::kPointLast]);
|
| }
|
| // check for one
|
| if (!(zeroOneSet & (kOneS1Set | kZeroS2Set))
|
| @@ -1636,15 +1768,15 @@ int SkTSect<TCurve>::EndsEqual(const SkTSect* sect1, const SkTSect* sect2,
|
| }
|
| if (!(zeroOneSet & (kOneS1Set | kOneS2Set))
|
| && sect1->fCurve[TCurve::kPointLast].approximatelyEqual(sect2->fCurve[
|
| - TCurve::kPointLast])) {
|
| + OppCurve::kPointLast])) {
|
| zeroOneSet |= kOneS1Set | kOneS2Set;
|
| intersections->insertNear(1, 1, sect1->fCurve[TCurve::kPointLast],
|
| - sect2->fCurve[TCurve::kPointLast]);
|
| + sect2->fCurve[OppCurve::kPointLast]);
|
| }
|
| return zeroOneSet;
|
| }
|
|
|
| -template<typename TCurve>
|
| +template<typename TCurve, typename OppCurve>
|
| struct SkClosestRecord {
|
| bool operator<(const SkClosestRecord& rh) const {
|
| return fClosest < rh.fClosest;
|
| @@ -1656,10 +1788,10 @@ struct SkClosestRecord {
|
| intersections->insert(r1t, r2t, fC1Span->part()[fC1Index]);
|
| }
|
|
|
| - void findEnd(const SkTSpan<TCurve>* span1, const SkTSpan<TCurve>* span2,
|
| + void findEnd(const SkTSpan<TCurve, OppCurve>* span1, const SkTSpan<OppCurve, TCurve>* span2,
|
| int c1Index, int c2Index) {
|
| const TCurve& c1 = span1->part();
|
| - const TCurve& c2 = span2->part();
|
| + const OppCurve& c2 = span2->part();
|
| if (!c1[c1Index].approximatelyEqual(c2[c2Index])) {
|
| return;
|
| }
|
| @@ -1700,7 +1832,8 @@ struct SkClosestRecord {
|
|
|
| void reset() {
|
| fClosest = FLT_MAX;
|
| - SkDEBUGCODE(fC1Span = fC2Span = NULL);
|
| + SkDEBUGCODE(fC1Span = NULL);
|
| + SkDEBUGCODE(fC2Span = NULL);
|
| SkDEBUGCODE(fC1Index = fC2Index = -1);
|
| }
|
|
|
| @@ -1711,8 +1844,8 @@ struct SkClosestRecord {
|
| fC2EndT = SkTMax(fC2EndT, mate.fC2EndT);
|
| }
|
|
|
| - const SkTSpan<TCurve>* fC1Span;
|
| - const SkTSpan<TCurve>* fC2Span;
|
| + const SkTSpan<TCurve, OppCurve>* fC1Span;
|
| + const SkTSpan<OppCurve, TCurve>* fC2Span;
|
| double fC1StartT;
|
| double fC1EndT;
|
| double fC2StartT;
|
| @@ -1722,24 +1855,24 @@ struct SkClosestRecord {
|
| int fC2Index;
|
| };
|
|
|
| -template<typename TCurve>
|
| +template<typename TCurve, typename OppCurve>
|
| struct SkClosestSect {
|
| SkClosestSect()
|
| : fUsed(0) {
|
| fClosest.push_back().reset();
|
| }
|
|
|
| - bool find(const SkTSpan<TCurve>* span1, const SkTSpan<TCurve>* span2) {
|
| - SkClosestRecord<TCurve>* record = &fClosest[fUsed];
|
| + bool find(const SkTSpan<TCurve, OppCurve>* span1, const SkTSpan<OppCurve, TCurve>* span2) {
|
| + SkClosestRecord<TCurve, OppCurve>* record = &fClosest[fUsed];
|
| record->findEnd(span1, span2, 0, 0);
|
| - record->findEnd(span1, span2, 0, TCurve::kPointLast);
|
| + record->findEnd(span1, span2, 0, OppCurve::kPointLast);
|
| record->findEnd(span1, span2, TCurve::kPointLast, 0);
|
| - record->findEnd(span1, span2, TCurve::kPointLast, TCurve::kPointLast);
|
| + record->findEnd(span1, span2, TCurve::kPointLast, OppCurve::kPointLast);
|
| if (record->fClosest == FLT_MAX) {
|
| return false;
|
| }
|
| for (int index = 0; index < fUsed; ++index) {
|
| - SkClosestRecord<TCurve>* test = &fClosest[index];
|
| + SkClosestRecord<TCurve, OppCurve>* test = &fClosest[index];
|
| if (test->matesWith(*record)) {
|
| if (test->fClosest > record->fClosest) {
|
| test->merge(*record);
|
| @@ -1755,34 +1888,37 @@ struct SkClosestSect {
|
| }
|
|
|
| void finish(SkIntersections* intersections) const {
|
| - SkSTArray<TCurve::kMaxIntersections * 2, const SkClosestRecord<TCurve>*, true> closestPtrs;
|
| + SkSTArray<TCurve::kMaxIntersections * 3,
|
| + const SkClosestRecord<TCurve, OppCurve>*, true> closestPtrs;
|
| for (int index = 0; index < fUsed; ++index) {
|
| closestPtrs.push_back(&fClosest[index]);
|
| }
|
| - SkTQSort<const SkClosestRecord<TCurve> >(closestPtrs.begin(), closestPtrs.end() - 1);
|
| + SkTQSort<const SkClosestRecord<TCurve, OppCurve> >(closestPtrs.begin(), closestPtrs.end()
|
| + - 1);
|
| for (int index = 0; index < fUsed; ++index) {
|
| - const SkClosestRecord<TCurve>* test = closestPtrs[index];
|
| + const SkClosestRecord<TCurve, OppCurve>* test = closestPtrs[index];
|
| test->addIntersection(intersections);
|
| }
|
| }
|
|
|
| // this is oversized so that an extra records can merge into final one
|
| - SkSTArray<TCurve::kMaxIntersections * 2, SkClosestRecord<TCurve>, true> fClosest;
|
| + SkSTArray<TCurve::kMaxIntersections * 2, SkClosestRecord<TCurve, OppCurve>, true> fClosest;
|
| int fUsed;
|
| };
|
|
|
| // returns true if the rect is too small to consider
|
| -template<typename TCurve>
|
| -void SkTSect<TCurve>::BinarySearch(SkTSect* sect1, SkTSect* sect2, SkIntersections* intersections) {
|
| +template<typename TCurve, typename OppCurve>
|
| +void SkTSect<TCurve, OppCurve>::BinarySearch(SkTSect<TCurve, OppCurve>* sect1,
|
| + SkTSect<OppCurve, TCurve>* sect2, SkIntersections* intersections) {
|
| #if DEBUG_T_SECT_DUMP > 1
|
| gDumpTSectNum = 0;
|
| #endif
|
| - PATH_OPS_DEBUG_CODE(sect1->fOppSect = sect2);
|
| - PATH_OPS_DEBUG_CODE(sect2->fOppSect = sect1);
|
| + SkDEBUGCODE(sect1->fOppSect = sect2);
|
| + SkDEBUGCODE(sect2->fOppSect = sect1);
|
| intersections->reset();
|
| - intersections->setMax(TCurve::kMaxIntersections * 2); // give extra for slop
|
| - SkTSpan<TCurve>* span1 = sect1->fHead;
|
| - SkTSpan<TCurve>* span2 = sect2->fHead;
|
| + intersections->setMax(TCurve::kMaxIntersections * 3); // give extra for slop
|
| + SkTSpan<TCurve, OppCurve>* span1 = sect1->fHead;
|
| + SkTSpan<OppCurve, TCurve>* span2 = sect2->fHead;
|
| int oppSect, sect = sect1->intersects(span1, sect2, span2, &oppSect);
|
| // SkASSERT(between(0, sect, 2));
|
| if (!sect) {
|
| @@ -1796,28 +1932,36 @@ void SkTSect<TCurve>::BinarySearch(SkTSect* sect1, SkTSect* sect2, SkIntersectio
|
| span2->addBounded(span1, §2->fHeap);
|
| do {
|
| // find the largest bounds
|
| - SkTSpan<TCurve>* largest1 = sect1->boundsMax();
|
| + SkTSpan<TCurve, OppCurve>* largest1 = sect1->boundsMax();
|
| if (!largest1) {
|
| break;
|
| }
|
| - SkTSpan<TCurve>* largest2 = sect2->boundsMax();
|
| - bool split1 = !largest2 || (largest1 && (largest1->fBoundsMax > largest2->fBoundsMax
|
| - || (!largest1->fCollapsed && largest2->fCollapsed)));
|
| + SkTSpan<OppCurve, TCurve>* largest2 = sect2->boundsMax();
|
| // split it
|
| - SkTSpan<TCurve>* half1 = split1 ? largest1 : largest2;
|
| - SkASSERT(half1);
|
| - if (half1->fCollapsed) {
|
| - break;
|
| - }
|
| - SkTSect* splitSect = split1 ? sect1 : sect2;
|
| - // trim parts that don't intersect the opposite
|
| - SkTSpan<TCurve>* half2 = splitSect->addOne();
|
| - SkTSect* unsplitSect = split1 ? sect2 : sect1;
|
| - if (!half2->split(half1, &splitSect->fHeap)) {
|
| - break;
|
| + if (!largest2 || (largest1 && (largest1->fBoundsMax > largest2->fBoundsMax
|
| + || (!largest1->fCollapsed && largest2->fCollapsed)))) {
|
| + if (largest1->fCollapsed) {
|
| + break;
|
| + }
|
| + // trim parts that don't intersect the opposite
|
| + SkTSpan<TCurve, OppCurve>* half1 = sect1->addOne();
|
| + if (!half1->split(largest1, §1->fHeap)) {
|
| + break;
|
| + }
|
| + sect1->trim(largest1, sect2);
|
| + sect1->trim(half1, sect2);
|
| + } else {
|
| + if (largest2->fCollapsed) {
|
| + break;
|
| + }
|
| + // trim parts that don't intersect the opposite
|
| + SkTSpan<OppCurve, TCurve>* half2 = sect2->addOne();
|
| + if (!half2->split(largest2, §2->fHeap)) {
|
| + break;
|
| + }
|
| + sect2->trim(largest2, sect1);
|
| + sect2->trim(half2, sect1);
|
| }
|
| - splitSect->trim(half1, unsplitSect);
|
| - splitSect->trim(half2, unsplitSect);
|
| sect1->validate();
|
| sect2->validate();
|
| // if there are 9 or more continuous spans on both sects, suspect coincidence
|
| @@ -1834,6 +1978,9 @@ void SkTSect<TCurve>::BinarySearch(SkTSect* sect1, SkTSect* sect2, SkIntersectio
|
| sect1->removeByPerpendicular(sect2);
|
| sect1->validate();
|
| sect2->validate();
|
| + if (sect1->collapsed() > TCurve::kMaxIntersections) {
|
| + break;
|
| + }
|
| }
|
| #if DEBUG_T_SECT_DUMP
|
| sect1->dumpBoth(sect2);
|
| @@ -1842,7 +1989,7 @@ void SkTSect<TCurve>::BinarySearch(SkTSect* sect1, SkTSect* sect2, SkIntersectio
|
| break;
|
| }
|
| } while (true);
|
| - SkTSpan<TCurve>* coincident = sect1->fCoincident;
|
| + SkTSpan<TCurve, OppCurve>* coincident = sect1->fCoincident;
|
| if (coincident) {
|
| // if there is more than one coincident span, check loosely to see if they should be joined
|
| if (coincident->fNext) {
|
| @@ -1862,15 +2009,15 @@ void SkTSect<TCurve>::BinarySearch(SkTSect* sect1, SkTSect* sect2, SkIntersectio
|
| }
|
| } while ((coincident = coincident->fNext));
|
| }
|
| + int zeroOneSet = EndsEqual(sect1, sect2, intersections);
|
| if (!sect1->fHead || !sect2->fHead) {
|
| return;
|
| }
|
| - int zeroOneSet = EndsEqual(sect1, sect2, intersections);
|
| sect1->recoverCollapsed();
|
| sect2->recoverCollapsed();
|
| - SkTSpan<TCurve>* result1 = sect1->fHead;
|
| + SkTSpan<TCurve, OppCurve>* result1 = sect1->fHead;
|
| // check heads and tails for zero and ones and insert them if we haven't already done so
|
| - const SkTSpan<TCurve>* head1 = result1;
|
| + const SkTSpan<TCurve, OppCurve>* head1 = result1;
|
| if (!(zeroOneSet & kZeroS1Set) && approximately_less_than_zero(head1->fStartT)) {
|
| const SkDPoint& start1 = sect1->fCurve[0];
|
| if (head1->isBounded()) {
|
| @@ -1880,7 +2027,7 @@ void SkTSect<TCurve>::BinarySearch(SkTSect* sect1, SkTSect* sect2, SkIntersectio
|
| }
|
| }
|
| }
|
| - const SkTSpan<TCurve>* head2 = sect2->fHead;
|
| + const SkTSpan<OppCurve, TCurve>* head2 = sect2->fHead;
|
| if (!(zeroOneSet & kZeroS2Set) && approximately_less_than_zero(head2->fStartT)) {
|
| const SkDPoint& start2 = sect2->fCurve[0];
|
| if (head2->isBounded()) {
|
| @@ -1890,7 +2037,7 @@ void SkTSect<TCurve>::BinarySearch(SkTSect* sect1, SkTSect* sect2, SkIntersectio
|
| }
|
| }
|
| }
|
| - const SkTSpan<TCurve>* tail1 = sect1->tail();
|
| + const SkTSpan<TCurve, OppCurve>* tail1 = sect1->tail();
|
| if (!(zeroOneSet & kOneS1Set) && approximately_greater_than_one(tail1->fEndT)) {
|
| const SkDPoint& end1 = sect1->fCurve[TCurve::kPointLast];
|
| if (tail1->isBounded()) {
|
| @@ -1900,9 +2047,9 @@ void SkTSect<TCurve>::BinarySearch(SkTSect* sect1, SkTSect* sect2, SkIntersectio
|
| }
|
| }
|
| }
|
| - const SkTSpan<TCurve>* tail2 = sect2->tail();
|
| + const SkTSpan<OppCurve, TCurve>* tail2 = sect2->tail();
|
| if (!(zeroOneSet & kOneS2Set) && approximately_greater_than_one(tail2->fEndT)) {
|
| - const SkDPoint& end2 = sect2->fCurve[TCurve::kPointLast];
|
| + const SkDPoint& end2 = sect2->fCurve[OppCurve::kPointLast];
|
| if (tail2->isBounded()) {
|
| double t = tail2->closestBoundedT(end2);
|
| if (sect1->fCurve.ptAtT(t).approximatelyEqual(end2)) {
|
| @@ -1910,7 +2057,7 @@ void SkTSect<TCurve>::BinarySearch(SkTSect* sect1, SkTSect* sect2, SkIntersectio
|
| }
|
| }
|
| }
|
| - SkClosestSect<TCurve> closest;
|
| + SkClosestSect<TCurve, OppCurve> closest;
|
| do {
|
| while (result1 && result1->fCoinStart.isCoincident() && result1->fCoinEnd.isCoincident()) {
|
| result1 = result1->fNext;
|
| @@ -1918,7 +2065,7 @@ void SkTSect<TCurve>::BinarySearch(SkTSect* sect1, SkTSect* sect2, SkIntersectio
|
| if (!result1) {
|
| break;
|
| }
|
| - SkTSpan<TCurve>* result2 = sect2->fHead;
|
| + SkTSpan<OppCurve, TCurve>* result2 = sect2->fHead;
|
| bool found = false;
|
| while (result2) {
|
| found |= closest.find(result1, result2);
|
| @@ -1936,7 +2083,7 @@ void SkTSect<TCurve>::BinarySearch(SkTSect* sect1, SkTSect* sect2, SkIntersectio
|
| double midT = ((*intersections)[0][index] + (*intersections)[0][index + 1]) / 2;
|
| SkDPoint midPt = sect1->fCurve.ptAtT(midT);
|
| // intersect perpendicular with opposite curve
|
| - SkTCoincident<TCurve> perp;
|
| + SkTCoincident<TCurve, OppCurve> perp;
|
| perp.setPerp(sect1->fCurve, midT, midPt, sect2->fCurve);
|
| if (!perp.isCoincident()) {
|
| ++index;
|
|
|