diff -r 000000000000 -r 6474c204b198 gfx/skia/trunk/src/pathops/SkOpContour.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gfx/skia/trunk/src/pathops/SkOpContour.h Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,269 @@ +/* + * 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 "SkOpSegment.h" +#include "SkTArray.h" + +class SkIntersections; +class SkOpContour; +class SkPathWriter; + +struct SkCoincidence { + SkOpContour* fOther; + int fSegments[2]; + double fTs[2][2]; + SkPoint fPts[2]; +}; + +class SkOpContour { +public: + SkOpContour() { + reset(); +#ifdef SK_DEBUG + fID = ++SkPathOpsDebug::gContourID; +#endif + } + + bool operator<(const SkOpContour& rh) const { + return fBounds.fTop == rh.fBounds.fTop + ? fBounds.fLeft < rh.fBounds.fLeft + : fBounds.fTop < rh.fBounds.fTop; + } + + bool addCoincident(int index, SkOpContour* other, int otherIndex, + const SkIntersections& ts, bool swap); + void addCoincidentPoints(); + + void addCross(const SkOpContour* crosser) { +#ifdef DEBUG_CROSS + for (int index = 0; index < fCrosses.count(); ++index) { + SkASSERT(fCrosses[index] != crosser); + } +#endif + fCrosses.push_back(crosser); + } + + void addCubic(const SkPoint pts[4]) { + fSegments.push_back().addCubic(pts, fOperand, fXor); + fContainsCurves = fContainsCubics = true; + } + + int addLine(const SkPoint pts[2]) { + fSegments.push_back().addLine(pts, fOperand, fXor); + return fSegments.count(); + } + + void addOtherT(int segIndex, int tIndex, double otherT, int otherIndex) { + fSegments[segIndex].addOtherT(tIndex, otherT, otherIndex); + } + + bool addPartialCoincident(int index, SkOpContour* other, int otherIndex, + const SkIntersections& ts, int ptIndex, bool swap); + + int addQuad(const SkPoint pts[3]) { + fSegments.push_back().addQuad(pts, fOperand, fXor); + fContainsCurves = true; + return fSegments.count(); + } + + int addT(int segIndex, SkOpContour* other, int otherIndex, const SkPoint& pt, double newT) { + setContainsIntercepts(); + return fSegments[segIndex].addT(&other->fSegments[otherIndex], pt, newT); + } + + int addSelfT(int segIndex, SkOpContour* other, int otherIndex, const SkPoint& pt, double newT) { + setContainsIntercepts(); + return fSegments[segIndex].addSelfT(&other->fSegments[otherIndex], pt, newT); + } + + const SkPathOpsBounds& bounds() const { + return fBounds; + } + + void calcCoincidentWinding(); + void calcPartialCoincidentWinding(); + + void checkEnds() { + if (!fContainsCurves) { + return; + } + int segmentCount = fSegments.count(); + for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { + SkOpSegment* segment = &fSegments[sIndex]; + if (segment->verb() == SkPath::kLine_Verb) { + continue; + } + if (segment->done()) { + continue; // likely coincident, nothing to do + } + segment->checkEnds(); + } + } + + // if same point has different T values, choose a common T + void checkTiny() { + int segmentCount = fSegments.count(); + if (segmentCount <= 2) { + return; + } + for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { + fSegments[sIndex].checkTiny(); + } + } + + void complete() { + setBounds(); + fContainsIntercepts = false; + } + + bool containsCubics() const { + return fContainsCubics; + } + + bool crosses(const SkOpContour* crosser) const { + for (int index = 0; index < fCrosses.count(); ++index) { + if (fCrosses[index] == crosser) { + return true; + } + } + return false; + } + + bool done() const { + return fDone; + } + + const SkPoint& end() const { + const SkOpSegment& segment = fSegments.back(); + return segment.pts()[SkPathOpsVerbToPoints(segment.verb())]; + } + + void fixOtherTIndex() { + int segmentCount = fSegments.count(); + for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { + fSegments[sIndex].fixOtherTIndex(); + } + } + + void joinCoincidence() { + joinCoincidence(fCoincidences, false); + joinCoincidence(fPartialCoincidences, true); + } + + SkOpSegment* nonVerticalSegment(int* start, int* end); + + bool operand() const { + return fOperand; + } + + void reset() { + fSegments.reset(); + fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax); + fContainsCurves = fContainsCubics = fContainsIntercepts = fDone = false; + } + + SkTArray& segments() { + return fSegments; + } + + void setContainsIntercepts() { + fContainsIntercepts = true; + } + + void setOperand(bool isOp) { + fOperand = isOp; + } + + void setOppXor(bool isOppXor) { + fOppXor = isOppXor; + int segmentCount = fSegments.count(); + for (int test = 0; test < segmentCount; ++test) { + fSegments[test].setOppXor(isOppXor); + } + } + + void setXor(bool isXor) { + fXor = isXor; + } + + void sortSegments(); + + const SkPoint& start() const { + return fSegments.front().pts()[0]; + } + + void toPath(SkPathWriter* path) const; + + void toPartialBackward(SkPathWriter* path) const { + int segmentCount = fSegments.count(); + for (int test = segmentCount - 1; test >= 0; --test) { + fSegments[test].addCurveTo(1, 0, path, true); + } + } + + void toPartialForward(SkPathWriter* path) const { + int segmentCount = fSegments.count(); + for (int test = 0; test < segmentCount; ++test) { + fSegments[test].addCurveTo(0, 1, path, true); + } + } + + void topSortableSegment(const SkPoint& topLeft, SkPoint* bestXY, SkOpSegment** topStart); + SkOpSegment* undoneSegment(int* start, int* end); + + int updateSegment(int index, const SkPoint* pts) { + SkOpSegment& segment = fSegments[index]; + segment.updatePts(pts); + return SkPathOpsVerbToPoints(segment.verb()) + 1; + } + +#if DEBUG_TEST + SkTArray& debugSegments() { + return fSegments; + } +#endif + +#if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY + void debugShowActiveSpans() { + for (int index = 0; index < fSegments.count(); ++index) { + fSegments[index].debugShowActiveSpans(); + } + } +#endif + +#if DEBUG_SHOW_WINDING + int debugShowWindingValues(int totalSegments, int ofInterest); + static void debugShowWindingValues(const SkTArray& contourList); +#endif + +private: + void calcCommonCoincidentWinding(const SkCoincidence& ); + void joinCoincidence(const SkTArray& , bool partial); + void setBounds(); + + SkTArray fSegments; + SkTArray fSortedSegments; + int fFirstSorted; + SkTArray fCoincidences; + SkTArray fPartialCoincidences; + SkTArray fCrosses; + SkPathOpsBounds fBounds; + bool fContainsIntercepts; // FIXME: is this used by anybody? + bool fContainsCubics; + bool fContainsCurves; + bool fDone; + bool fOperand; // true for the second argument to a binary operator + bool fXor; + bool fOppXor; +#ifdef SK_DEBUG + int fID; +#endif +}; + +#endif