123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454 |
- /*
- * Copyright 2013 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #ifndef SkOpContour_DEFINED
- #define SkOpContour_DEFINED
- #include "include/private/SkTDArray.h"
- #include "src/core/SkTSort.h"
- #include "src/pathops/SkOpSegment.h"
- enum class SkOpRayDir;
- struct SkOpRayHit;
- class SkPathWriter;
- class SkOpContour {
- public:
- SkOpContour() {
- reset();
- }
- bool operator<(const SkOpContour& rh) const {
- return fBounds.fTop == rh.fBounds.fTop
- ? fBounds.fLeft < rh.fBounds.fLeft
- : fBounds.fTop < rh.fBounds.fTop;
- }
- void addConic(SkPoint pts[3], SkScalar weight) {
- appendSegment().addConic(pts, weight, this);
- }
- void addCubic(SkPoint pts[4]) {
- appendSegment().addCubic(pts, this);
- }
- SkOpSegment* addLine(SkPoint pts[2]) {
- SkASSERT(pts[0] != pts[1]);
- return appendSegment().addLine(pts, this);
- }
- void addQuad(SkPoint pts[3]) {
- appendSegment().addQuad(pts, this);
- }
- SkOpSegment& appendSegment() {
- SkOpSegment* result = fCount++ ? this->globalState()->allocator()->make<SkOpSegment>()
- : &fHead;
- result->setPrev(fTail);
- if (fTail) {
- fTail->setNext(result);
- }
- fTail = result;
- return *result;
- }
- const SkPathOpsBounds& bounds() const {
- return fBounds;
- }
- void calcAngles() {
- SkASSERT(fCount > 0);
- SkOpSegment* segment = &fHead;
- do {
- segment->calcAngles();
- } while ((segment = segment->next()));
- }
- void complete() {
- setBounds();
- }
- int count() const {
- return fCount;
- }
- int debugID() const {
- return SkDEBUGRELEASE(fID, -1);
- }
- int debugIndent() const {
- return SkDEBUGRELEASE(fDebugIndent, 0);
- }
- const SkOpAngle* debugAngle(int id) const {
- return SkDEBUGRELEASE(this->globalState()->debugAngle(id), nullptr);
- }
- const SkOpCoincidence* debugCoincidence() const {
- return this->globalState()->coincidence();
- }
- #if DEBUG_COIN
- void debugCheckHealth(SkPathOpsDebug::GlitchLog* ) const;
- #endif
- SkOpContour* debugContour(int id) const {
- return SkDEBUGRELEASE(this->globalState()->debugContour(id), nullptr);
- }
- #if DEBUG_COIN
- void debugMissingCoincidence(SkPathOpsDebug::GlitchLog* log) const;
- void debugMoveMultiples(SkPathOpsDebug::GlitchLog* ) const;
- void debugMoveNearby(SkPathOpsDebug::GlitchLog* log) const;
- #endif
- const SkOpPtT* debugPtT(int id) const {
- return SkDEBUGRELEASE(this->globalState()->debugPtT(id), nullptr);
- }
- const SkOpSegment* debugSegment(int id) const {
- return SkDEBUGRELEASE(this->globalState()->debugSegment(id), nullptr);
- }
- #if DEBUG_ACTIVE_SPANS
- void debugShowActiveSpans(SkString* str) {
- SkOpSegment* segment = &fHead;
- do {
- segment->debugShowActiveSpans(str);
- } while ((segment = segment->next()));
- }
- #endif
- const SkOpSpanBase* debugSpan(int id) const {
- return SkDEBUGRELEASE(this->globalState()->debugSpan(id), nullptr);
- }
- SkOpGlobalState* globalState() const {
- return fState;
- }
- void debugValidate() const {
- #if DEBUG_VALIDATE
- const SkOpSegment* segment = &fHead;
- const SkOpSegment* prior = nullptr;
- do {
- segment->debugValidate();
- SkASSERT(segment->prev() == prior);
- prior = segment;
- } while ((segment = segment->next()));
- SkASSERT(prior == fTail);
- #endif
- }
- bool done() const {
- return fDone;
- }
- void dump() const;
- void dumpAll() const;
- void dumpAngles() const;
- void dumpContours() const;
- void dumpContoursAll() const;
- void dumpContoursAngles() const;
- void dumpContoursPts() const;
- void dumpContoursPt(int segmentID) const;
- void dumpContoursSegment(int segmentID) const;
- void dumpContoursSpan(int segmentID) const;
- void dumpContoursSpans() const;
- void dumpPt(int ) const;
- void dumpPts(const char* prefix = "seg") const;
- void dumpPtsX(const char* prefix) const;
- void dumpSegment(int ) const;
- void dumpSegments(const char* prefix = "seg", SkPathOp op = (SkPathOp) -1) const;
- void dumpSpan(int ) const;
- void dumpSpans() const;
- const SkPoint& end() const {
- return fTail->pts()[SkPathOpsVerbToPoints(fTail->verb())];
- }
- SkOpSpan* findSortableTop(SkOpContour* );
- SkOpSegment* first() {
- SkASSERT(fCount > 0);
- return &fHead;
- }
- const SkOpSegment* first() const {
- SkASSERT(fCount > 0);
- return &fHead;
- }
- void indentDump() const {
- SkDEBUGCODE(fDebugIndent += 2);
- }
- void init(SkOpGlobalState* globalState, bool operand, bool isXor) {
- fState = globalState;
- fOperand = operand;
- fXor = isXor;
- SkDEBUGCODE(fID = globalState->nextContourID());
- }
- int isCcw() const {
- return fCcw;
- }
- bool isXor() const {
- return fXor;
- }
- void joinSegments() {
- SkOpSegment* segment = &fHead;
- SkOpSegment* next;
- do {
- next = segment->next();
- segment->joinEnds(next ? next : &fHead);
- } while ((segment = next));
- }
- void markAllDone() {
- SkOpSegment* segment = &fHead;
- do {
- segment->markAllDone();
- } while ((segment = segment->next()));
- }
- // Please keep this aligned with debugMissingCoincidence()
- bool missingCoincidence() {
- SkASSERT(fCount > 0);
- SkOpSegment* segment = &fHead;
- bool result = false;
- do {
- if (segment->missingCoincidence()) {
- result = true;
- }
- segment = segment->next();
- } while (segment);
- return result;
- }
- bool moveMultiples() {
- SkASSERT(fCount > 0);
- SkOpSegment* segment = &fHead;
- do {
- if (!segment->moveMultiples()) {
- return false;
- }
- } while ((segment = segment->next()));
- return true;
- }
- bool moveNearby() {
- SkASSERT(fCount > 0);
- SkOpSegment* segment = &fHead;
- do {
- if (!segment->moveNearby()) {
- return false;
- }
- } while ((segment = segment->next()));
- return true;
- }
- SkOpContour* next() {
- return fNext;
- }
- const SkOpContour* next() const {
- return fNext;
- }
- bool operand() const {
- return fOperand;
- }
- bool oppXor() const {
- return fOppXor;
- }
- void outdentDump() const {
- SkDEBUGCODE(fDebugIndent -= 2);
- }
- void rayCheck(const SkOpRayHit& base, SkOpRayDir dir, SkOpRayHit** hits, SkArenaAlloc*);
- void reset() {
- fTail = nullptr;
- fNext = nullptr;
- fCount = 0;
- fDone = false;
- SkDEBUGCODE(fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMin, SK_ScalarMin));
- SkDEBUGCODE(fFirstSorted = -1);
- SkDEBUGCODE(fDebugIndent = 0);
- }
- void resetReverse() {
- SkOpContour* next = this;
- do {
- if (!next->count()) {
- continue;
- }
- next->fCcw = -1;
- next->fReverse = false;
- } while ((next = next->next()));
- }
- bool reversed() const {
- return fReverse;
- }
- void setBounds() {
- SkASSERT(fCount > 0);
- const SkOpSegment* segment = &fHead;
- fBounds = segment->bounds();
- while ((segment = segment->next())) {
- fBounds.add(segment->bounds());
- }
- }
- void setCcw(int ccw) {
- fCcw = ccw;
- }
- void setGlobalState(SkOpGlobalState* state) {
- fState = state;
- }
- void setNext(SkOpContour* contour) {
- // SkASSERT(!fNext == !!contour);
- fNext = contour;
- }
- void setOperand(bool isOp) {
- fOperand = isOp;
- }
- void setOppXor(bool isOppXor) {
- fOppXor = isOppXor;
- }
- void setReverse() {
- fReverse = true;
- }
- void setXor(bool isXor) {
- fXor = isXor;
- }
- bool sortAngles() {
- SkASSERT(fCount > 0);
- SkOpSegment* segment = &fHead;
- do {
- FAIL_IF(!segment->sortAngles());
- } while ((segment = segment->next()));
- return true;
- }
- const SkPoint& start() const {
- return fHead.pts()[0];
- }
- void toPartialBackward(SkPathWriter* path) const {
- const SkOpSegment* segment = fTail;
- do {
- SkAssertResult(segment->addCurveTo(segment->tail(), segment->head(), path));
- } while ((segment = segment->prev()));
- }
- void toPartialForward(SkPathWriter* path) const {
- const SkOpSegment* segment = &fHead;
- do {
- SkAssertResult(segment->addCurveTo(segment->head(), segment->tail(), path));
- } while ((segment = segment->next()));
- }
- void toReversePath(SkPathWriter* path) const;
- void toPath(SkPathWriter* path) const;
- SkOpSpan* undoneSpan();
- protected:
- SkOpGlobalState* fState;
- SkOpSegment fHead;
- SkOpSegment* fTail;
- SkOpContour* fNext;
- SkPathOpsBounds fBounds;
- int fCcw;
- int fCount;
- int fFirstSorted;
- bool fDone; // set by find top segment
- bool fOperand; // true for the second argument to a binary operator
- bool fReverse; // true if contour should be reverse written to path (used only by fix winding)
- bool fXor; // set if original path had even-odd fill
- bool fOppXor; // set if opposite path had even-odd fill
- SkDEBUGCODE(int fID);
- SkDEBUGCODE(mutable int fDebugIndent);
- };
- class SkOpContourHead : public SkOpContour {
- public:
- SkOpContour* appendContour() {
- SkOpContour* contour = this->globalState()->allocator()->make<SkOpContour>();
- contour->setNext(nullptr);
- SkOpContour* prev = this;
- SkOpContour* next;
- while ((next = prev->next())) {
- prev = next;
- }
- prev->setNext(contour);
- return contour;
- }
- void joinAllSegments() {
- SkOpContour* next = this;
- do {
- if (!next->count()) {
- continue;
- }
- next->joinSegments();
- } while ((next = next->next()));
- }
- void remove(SkOpContour* contour) {
- if (contour == this) {
- SkASSERT(this->count() == 0);
- return;
- }
- SkASSERT(contour->next() == nullptr);
- SkOpContour* prev = this;
- SkOpContour* next;
- while ((next = prev->next()) != contour) {
- SkASSERT(next);
- prev = next;
- }
- SkASSERT(prev);
- prev->setNext(nullptr);
- }
- };
- class SkOpContourBuilder {
- public:
- SkOpContourBuilder(SkOpContour* contour)
- : fContour(contour)
- , fLastIsLine(false) {
- }
- void addConic(SkPoint pts[3], SkScalar weight);
- void addCubic(SkPoint pts[4]);
- void addCurve(SkPath::Verb verb, const SkPoint pts[4], SkScalar weight = 1);
- void addLine(const SkPoint pts[2]);
- void addQuad(SkPoint pts[3]);
- void flush();
- SkOpContour* contour() { return fContour; }
- void setContour(SkOpContour* contour) { flush(); fContour = contour; }
- protected:
- SkOpContour* fContour;
- SkPoint fLastLine[2];
- bool fLastIsLine;
- };
- #endif
|