| /* |
| * Copyright 2014 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| #ifndef SkCubicSpan_DEFINE |
| #define SkCubicSpan_DEFINE |
| |
| #include "SkChunkAlloc.h" |
| #include "SkPathOpsRect.h" |
| #include "SkPathOpsCubic.h" |
| #include "SkTArray.h" |
| |
| class SkIntersections; |
| |
| class SkCubicCoincident { |
| public: |
| bool isCoincident() const { |
| return fCoincident; |
| } |
| |
| void init() { |
| fCoincident = false; |
| SkDEBUGCODE(fPerpPt.fX = fPerpPt.fY = SK_ScalarNaN); |
| SkDEBUGCODE(fPerpT = SK_ScalarNaN); |
| } |
| |
| void markCoincident() { |
| if (!fCoincident) { |
| fPerpT = -1; |
| } |
| fCoincident = true; |
| } |
| |
| const SkDPoint& perpPt() const { |
| return fPerpPt; |
| } |
| |
| double perpT() const { |
| return fPerpT; |
| } |
| |
| void setPerp(const SkDCubic& cubic1, double t, const SkDPoint& qPt, const SkDCubic& cubic2); |
| |
| private: |
| SkDPoint fPerpPt; |
| double fPerpT; // perpendicular intersection on opposite Cubic |
| bool fCoincident; |
| }; |
| |
| class SkCubicSect; // used only by debug id |
| |
| class SkCubicSpan { |
| public: |
| void init(const SkDCubic& Cubic); |
| void initBounds(const SkDCubic& Cubic); |
| |
| bool contains(double t) const { |
| return !! const_cast<SkCubicSpan*>(this)->innerFind(t); |
| } |
| |
| bool contains(const SkCubicSpan* span) const; |
| |
| SkCubicSpan* find(double t) { |
| SkCubicSpan* result = innerFind(t); |
| SkASSERT(result); |
| return result; |
| } |
| |
| bool intersects(const SkCubicSpan* span) const; |
| |
| const SkCubicSpan* next() const { |
| return fNext; |
| } |
| |
| void reset() { |
| fBounded.reset(); |
| } |
| |
| bool split(SkCubicSpan* work) { |
| return splitAt(work, (work->fStartT + work->fEndT) * 0.5); |
| } |
| |
| bool splitAt(SkCubicSpan* work, double t); |
| bool tightBoundsIntersects(const SkCubicSpan* span) const; |
| |
| // implementation is for testing only |
| void dump() const; |
| |
| private: |
| bool hullIntersects(const SkDCubic& ) const; |
| SkCubicSpan* innerFind(double t); |
| bool linearIntersects(const SkDCubic& ) const; |
| |
| // implementation is for testing only |
| #if DEBUG_BINARY_CUBIC |
| int debugID(const SkCubicSect* ) const { return fDebugID; } |
| #else |
| int debugID(const SkCubicSect* ) const; |
| #endif |
| void dump(const SkCubicSect* ) const; |
| void dumpID(const SkCubicSect* ) const; |
| |
| #if DEBUG_BINARY_CUBIC |
| void validate() const; |
| #endif |
| |
| SkDCubic fPart; |
| SkCubicCoincident fCoinStart; |
| SkCubicCoincident fCoinEnd; |
| SkSTArray<4, SkCubicSpan*, true> fBounded; |
| SkCubicSpan* fPrev; |
| SkCubicSpan* fNext; |
| SkDRect fBounds; |
| double fStartT; |
| double fEndT; |
| double fBoundsMax; |
| bool fCollapsed; |
| bool fHasPerp; |
| mutable bool fIsLinear; |
| #if DEBUG_BINARY_CUBIC |
| int fDebugID; |
| bool fDebugDeleted; |
| #endif |
| friend class SkCubicSect; |
| }; |
| |
| class SkCubicSect { |
| public: |
| SkCubicSect(const SkDCubic& Cubic PATH_OPS_DEBUG_PARAMS(int id)); |
| static void BinarySearch(SkCubicSect* sect1, SkCubicSect* sect2, SkIntersections* intersections); |
| |
| // for testing only |
| void dumpCubics() const; |
| private: |
| SkCubicSpan* addOne(); |
| bool binarySearchCoin(const SkCubicSect& , double tStart, double tStep, double* t, |
| double* oppT); |
| SkCubicSpan* boundsMax() const; |
| void coincidentCheck(SkCubicSect* sect2); |
| bool intersects(const SkCubicSpan* span, const SkCubicSect* opp, const SkCubicSpan* oppSpan) const; |
| void onCurveCheck(SkCubicSect* sect2, SkCubicSpan* first, SkCubicSpan* last); |
| void recoverCollapsed(); |
| void removeSpan(SkCubicSpan* span); |
| void removeOne(const SkCubicSpan* test, SkCubicSpan* span); |
| void removeSpans(SkCubicSpan* span, SkCubicSect* opp); |
| void setPerp(const SkDCubic& opp, SkCubicSpan* first, SkCubicSpan* last); |
| void trim(SkCubicSpan* span, SkCubicSect* opp); |
| |
| // for testing only |
| void dump() const; |
| void dumpBoth(const SkCubicSect& opp) const; |
| void dumpBoth(const SkCubicSect* opp) const; |
| |
| #if DEBUG_BINARY_CUBIC |
| int debugID() const { return fDebugID; } |
| void validate() const; |
| #else |
| int debugID() const { return 0; } |
| #endif |
| const SkDCubic& fCubic; |
| SkChunkAlloc fHeap; |
| SkCubicSpan* fHead; |
| SkCubicSpan* fDeleted; |
| int fActiveCount; |
| #if DEBUG_BINARY_CUBIC |
| int fDebugID; |
| int fDebugCount; |
| int fDebugAllocatedCount; |
| #endif |
| friend class SkCubicSpan; // only used by debug id |
| }; |
| |
| #endif |