blob: 57f1aa08d862a201d3a8d98f40cd61211f913d8e [file] [log] [blame]
/*
* 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 SkQuadSpan_DEFINE
#define SkQuadSpan_DEFINE
#include "SkChunkAlloc.h"
#include "SkPathOpsRect.h"
#include "SkPathOpsQuad.h"
#include "SkTArray.h"
class SkIntersections;
class SkQuadCoincident {
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 SkDQuad& quad1, double t, const SkDPoint& qPt, const SkDQuad& quad2);
private:
SkDPoint fPerpPt;
double fPerpT; // perpendicular intersection on opposite quad
bool fCoincident;
};
class SkQuadSect; // used only by debug id
class SkQuadSpan {
public:
void init(const SkDQuad& quad);
void initBounds(const SkDQuad& quad);
bool contains(double t) const {
return !! const_cast<SkQuadSpan*>(this)->innerFind(t);
}
bool contains(const SkQuadSpan* span) const;
SkQuadSpan* find(double t) {
SkQuadSpan* result = innerFind(t);
SkASSERT(result);
return result;
}
bool intersects(const SkQuadSpan* span) const;
const SkQuadSpan* next() const {
return fNext;
}
void reset() {
fBounded.reset();
}
bool split(SkQuadSpan* work) {
return splitAt(work, (work->fStartT + work->fEndT) * 0.5);
}
bool splitAt(SkQuadSpan* work, double t);
bool tightBoundsIntersects(const SkQuadSpan* span) const;
// implementation is for testing only
void dump() const;
private:
bool hullIntersects(const SkDQuad& q2) const;
SkQuadSpan* innerFind(double t);
bool linearIntersects(const SkDQuad& q2) const;
// implementation is for testing only
#if DEBUG_BINARY_QUAD
int debugID(const SkQuadSect* ) const { return fDebugID; }
#else
int debugID(const SkQuadSect* ) const;
#endif
void dump(const SkQuadSect* ) const;
void dumpID(const SkQuadSect* ) const;
#if DEBUG_BINARY_QUAD
void validate() const;
#endif
SkDQuad fPart;
SkQuadCoincident fCoinStart;
SkQuadCoincident fCoinEnd;
SkSTArray<4, SkQuadSpan*, true> fBounded;
SkQuadSpan* fPrev;
SkQuadSpan* fNext;
SkDRect fBounds;
double fStartT;
double fEndT;
double fBoundsMax;
bool fCollapsed;
bool fHasPerp;
mutable bool fIsLinear;
#if DEBUG_BINARY_QUAD
int fDebugID;
bool fDebugDeleted;
#endif
friend class SkQuadSect;
};
class SkQuadSect {
public:
SkQuadSect(const SkDQuad& quad PATH_OPS_DEBUG_PARAMS(int id));
static void BinarySearch(SkQuadSect* sect1, SkQuadSect* sect2, SkIntersections* intersections);
// for testing only
void dumpQuads() const;
private:
SkQuadSpan* addOne();
bool binarySearchCoin(const SkQuadSect& , double tStart, double tStep, double* t, double* oppT);
SkQuadSpan* boundsMax() const;
void coincidentCheck(SkQuadSect* sect2);
bool intersects(const SkQuadSpan* span, const SkQuadSect* opp, const SkQuadSpan* oppSpan) const;
void onCurveCheck(SkQuadSect* sect2, SkQuadSpan* first, SkQuadSpan* last);
void recoverCollapsed();
void removeSpan(SkQuadSpan* span);
void removeOne(const SkQuadSpan* test, SkQuadSpan* span);
void removeSpans(SkQuadSpan* span, SkQuadSect* opp);
void setPerp(const SkDQuad& opp, SkQuadSpan* first, SkQuadSpan* last);
const SkQuadSpan* tail() const;
void trim(SkQuadSpan* span, SkQuadSect* opp);
// for testing only
void dump() const;
void dumpBoth(const SkQuadSect& opp) const;
void dumpBoth(const SkQuadSect* opp) const;
#if DEBUG_BINARY_QUAD
int debugID() const { return fDebugID; }
void validate() const;
#else
int debugID() const { return 0; }
#endif
const SkDQuad& fQuad;
SkChunkAlloc fHeap;
SkQuadSpan* fHead;
SkQuadSpan* fDeleted;
int fActiveCount;
#if DEBUG_BINARY_QUAD
int fDebugID;
int fDebugCount;
int fDebugAllocatedCount;
#endif
friend class SkQuadSpan; // only used by debug id
};
#endif