Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1324)

Unified Diff: src/pathops/SkOpSegment.h

Issue 13094010: Add implementation of path ops (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/pathops/SkOpEdgeBuilder.cpp ('k') | src/pathops/SkOpSegment.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/pathops/SkOpSegment.h
===================================================================
--- src/pathops/SkOpSegment.h (revision 0)
+++ src/pathops/SkOpSegment.h (revision 0)
@@ -0,0 +1,410 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkOpSegment_DEFINE
+#define SkOpSegment_DEFINE
+
+#include "SkOpAngle.h"
+#include "SkPathOpsBounds.h"
+#include "SkPathOpsCurve.h"
+#include "SkTDArray.h"
+
+class SkPathWriter;
+
+class SkOpSegment {
+public:
+ SkOpSegment() {
+#if DEBUG_DUMP
+ fID = ++gSegmentID;
+#endif
+ }
+
+ bool operator<(const SkOpSegment& rh) const {
+ return fBounds.fTop < rh.fBounds.fTop;
+ }
+
+ const SkPathOpsBounds& bounds() const {
+ return fBounds;
+ }
+
+ // OPTIMIZE
+ // when the edges are initially walked, they don't automatically get the prior and next
+ // edges assigned to positions t=0 and t=1. Doing that would remove the need for this check,
+ // and would additionally remove the need for similar checks in condition edges. It would
+ // also allow intersection code to assume end of segment intersections (maybe?)
+ bool complete() const {
+ int count = fTs.count();
+ return count > 1 && fTs[0].fT == 0 && fTs[--count].fT == 1;
+ }
+
+ bool done() const {
+ SkASSERT(fDoneSpans <= fTs.count());
+ return fDoneSpans == fTs.count();
+ }
+
+ bool done(int min) const {
+ return fTs[min].fDone;
+ }
+
+ bool done(const SkOpAngle* angle) const {
+ return done(SkMin32(angle->start(), angle->end()));
+ }
+
+ SkVector dxdy(int index) const {
+ return (*CurveSlopeAtT[fVerb])(fPts, fTs[index].fT);
+ }
+
+ SkScalar dy(int index) const {
+ return dxdy(index).fY;
+ }
+
+ bool intersected() const {
+ return fTs.count() > 0;
+ }
+
+ bool isCanceled(int tIndex) const {
+ return fTs[tIndex].fWindValue == 0 && fTs[tIndex].fOppValue == 0;
+ }
+
+ bool isConnected(int startIndex, int endIndex) const {
+ return fTs[startIndex].fWindSum != SK_MinS32 || fTs[endIndex].fWindSum != SK_MinS32;
+ }
+
+ bool isHorizontal() const {
+ return fBounds.fTop == fBounds.fBottom;
+ }
+
+ bool isVertical() const {
+ return fBounds.fLeft == fBounds.fRight;
+ }
+
+ bool isVertical(int start, int end) const {
+ return (*CurveIsVertical[fVerb])(fPts, start, end);
+ }
+
+ bool operand() const {
+ return fOperand;
+ }
+
+ int oppSign(const SkOpAngle* angle) const {
+ SkASSERT(angle->segment() == this);
+ return oppSign(angle->start(), angle->end());
+ }
+
+ int oppSign(int startIndex, int endIndex) const {
+ int result = startIndex < endIndex ? -fTs[startIndex].fOppValue : fTs[endIndex].fOppValue;
+#if DEBUG_WIND_BUMP
+ SkDebugf("%s oppSign=%d\n", __FUNCTION__, result);
+#endif
+ return result;
+ }
+
+ int oppSum(int tIndex) const {
+ return fTs[tIndex].fOppSum;
+ }
+
+ int oppSum(const SkOpAngle* angle) const {
+ int lesser = SkMin32(angle->start(), angle->end());
+ return fTs[lesser].fOppSum;
+ }
+
+ int oppValue(int tIndex) const {
+ return fTs[tIndex].fOppValue;
+ }
+
+ int oppValue(const SkOpAngle* angle) const {
+ int lesser = SkMin32(angle->start(), angle->end());
+ return fTs[lesser].fOppValue;
+ }
+
+ const SkPoint* pts() const {
+ return fPts;
+ }
+
+ void reset() {
+ init(NULL, (SkPath::Verb) -1, false, false);
+ fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax);
+ fTs.reset();
+ }
+
+ void setOppXor(bool isOppXor) {
+ fOppXor = isOppXor;
+ }
+
+ void setSpanT(int index, double t) {
+ SkOpSpan& span = fTs[index];
+ span.fT = t;
+ span.fOther->fTs[span.fOtherIndex].fOtherT = t;
+ }
+
+ void setUpWinding(int index, int endIndex, int& maxWinding, int& sumWinding) {
+ int deltaSum = spanSign(index, endIndex);
+ maxWinding = sumWinding;
+ sumWinding = sumWinding -= deltaSum;
+ }
+
+ // OPTIMIZATION: mark as debugging only if used solely by tests
+ const SkOpSpan& span(int tIndex) const {
+ return fTs[tIndex];
+ }
+
+ int spanSign(const SkOpAngle* angle) const {
+ SkASSERT(angle->segment() == this);
+ return spanSign(angle->start(), angle->end());
+ }
+
+ int spanSign(int startIndex, int endIndex) const {
+ int result = startIndex < endIndex ? -fTs[startIndex].fWindValue : fTs[endIndex].fWindValue;
+#if DEBUG_WIND_BUMP
+ SkDebugf("%s spanSign=%d\n", __FUNCTION__, result);
+#endif
+ return result;
+ }
+
+ // OPTIMIZATION: mark as debugging only if used solely by tests
+ double t(int tIndex) const {
+ return fTs[tIndex].fT;
+ }
+
+ double tAtMid(int start, int end, double mid) const {
+ return fTs[start].fT * (1 - mid) + fTs[end].fT * mid;
+ }
+
+ bool unsortable(int index) const {
+ return fTs[index].fUnsortableStart || fTs[index].fUnsortableEnd;
+ }
+
+ void updatePts(const SkPoint pts[]) {
+ fPts = pts;
+ }
+
+ SkPath::Verb verb() const {
+ return fVerb;
+ }
+
+ int windSum(int tIndex) const {
+ return fTs[tIndex].fWindSum;
+ }
+
+ int windValue(int tIndex) const {
+ return fTs[tIndex].fWindValue;
+ }
+
+ SkScalar xAtT(int index) const {
+ return xAtT(&fTs[index]);
+ }
+
+ SkScalar xAtT(const SkOpSpan* span) const {
+ return xyAtT(span).fX;
+ }
+
+ const SkPoint& xyAtT(const SkOpSpan* span) const {
+ return span->fPt;
+ }
+
+ // used only by right angle winding finding
+ SkPoint xyAtT(double mid) const {
+ return (*CurvePointAtT[fVerb])(fPts, mid);
+ }
+
+ const SkPoint& xyAtT(int index) const {
+ return xyAtT(&fTs[index]);
+ }
+
+ SkScalar yAtT(int index) const {
+ return yAtT(&fTs[index]);
+ }
+
+ SkScalar yAtT(const SkOpSpan* span) const {
+ return xyAtT(span).fY;
+ }
+
+ bool activeAngle(int index, int& done, SkTDArray<SkOpAngle>& angles);
+ bool activeAngleOther(int index, int& done, SkTDArray<SkOpAngle>& angles);
+ bool activeAngleInner(int index, int& done, SkTDArray<SkOpAngle>& angles);
+ SkPoint activeLeftTop(bool onlySortable, int* firstT) const;
+ bool activeOp(int index, int endIndex, int xorMiMask, int xorSuMask, SkPathOp op);
+ bool activeOp(int xorMiMask, int xorSuMask, int index, int endIndex, SkPathOp op,
+ int& sumMiWinding, int& sumSuWinding, int& maxWinding, int& sumWinding,
+ int& oppMaxWinding, int& oppSumWinding);
+ bool activeWinding(int index, int endIndex);
+ bool activeWinding(int index, int endIndex, int& maxWinding, int& sumWinding);
+ void addAngle(SkTDArray<SkOpAngle>& angles, int start, int end) const;
+ void addCancelOutsides(double tStart, double oStart, SkOpSegment& other, double oEnd);
+ void addCoinOutsides(const SkTDArray<double>& outsideTs, SkOpSegment& other, double oEnd);
+ void addCubic(const SkPoint pts[4], bool operand, bool evenOdd);
+ void addCurveTo(int start, int end, SkPathWriter& path, bool active) const;
+ void addLine(const SkPoint pts[2], bool operand, bool evenOdd);
+ void addOtherT(int index, double otherT, int otherIndex);
+ void addQuad(const SkPoint pts[3], bool operand, bool evenOdd);
+ int addSelfT(SkOpSegment* other, const SkPoint& pt, double newT);
+ int addT(SkOpSegment* other, const SkPoint& pt, double newT);
+ void addTCancel(double startT, double endT, SkOpSegment& other, double oStartT, double oEndT);
+ void addTCoincident(double startT, double endT, SkOpSegment& other, double oStartT,
+ double oEndT);
+ void addTPair(double t, SkOpSegment& other, double otherT, bool borrowWind, const SkPoint& pt);
+ void addTwoAngles(int start, int end, SkTDArray<SkOpAngle>& angles) const;
+
+ int addUnsortableT(SkOpSegment* other, bool start, const SkPoint& pt, double newT);
+ int advanceCoincidentOther(const SkOpSpan* test, double oEndT, int& oIndex);
+ int advanceCoincidentThis(const SkOpSpan* oTest, bool opp, int index);
+ bool betweenTs(int lesser, double testT, int greater);
+ void buildAngles(int index, SkTDArray<SkOpAngle>& angles, bool includeOpp) const;
+ void buildAnglesInner(int index, SkTDArray<SkOpAngle>& angles) const;
+ int bumpCoincidentThis(const SkOpSpan* oTest, bool opp, int index,
+ SkTDArray<double>& outsideTs);
+ int bumpCoincidentOther(const SkOpSpan* test, double oEndT, int& oIndex,
+ SkTDArray<double>& oOutsideTs);
+ bool bumpSpan(SkOpSpan* span, int windDelta, int oppDelta);
+ bool clockwise(int tStart, int tEnd) const;
+ int computeSum(int startIndex, int endIndex, bool binary);
+ int crossedSpanY(const SkPoint& basePt, SkScalar& bestY, double& hitT, bool& hitSomething,
+ double mid, bool opp, bool current) const;
+ void decrementSpan(SkOpSpan* span);
+ bool equalPoints(int greaterTIndex, int lesserTIndex);
+ SkOpSegment* findNextOp(SkTDArray<SkOpSpan*>& chase, int& nextStart, int& nextEnd,
+ bool& unsortable, SkPathOp op, const int xorMiMask,
+ const int xorSuMask);
+ int findStartingEdge(SkTDArray<SkOpAngle*>& sorted, int start, int end);
+ SkOpSegment* findNextWinding(SkTDArray<SkOpSpan*>& chase, int& nextStart, int& nextEnd,
+ bool& unsortable);
+ SkOpSegment* findNextXor(int& nextStart, int& nextEnd, bool& unsortable);
+ void findTooCloseToCall();
+ SkOpSegment* findTop(int& tIndex, int& endIndex, bool& unsortable, bool onlySortable);
+ void fixOtherTIndex();
+ void init(const SkPoint pts[], SkPath::Verb verb, bool operand, bool evenOdd);
+ void initWinding(int start, int end);
+ void initWinding(int start, int end, int winding, int oppWinding);
+ void initWinding(int start, int end, double tHit, int winding, SkScalar hitDx, int oppWind,
+ SkScalar hitOppDx);
+ bool isLinear(int start, int end) const;
+ bool isMissing(double startT) const;
+ bool isSimple(int end) const;
+ SkOpSpan* markAndChaseDone(const SkOpAngle* angle, int winding);
+ SkOpSpan* markAndChaseDone(int index, int endIndex, int winding);
+ SkOpSpan* markAndChaseDoneBinary(const SkOpAngle* angle, int winding, int oppWinding);
+ SkOpSpan* markAndChaseDoneBinary(int index, int endIndex);
+ SkOpSpan* markAndChaseDoneUnary(int index, int endIndex);
+ SkOpSpan* markAndChaseDoneUnary(const SkOpAngle* angle, int winding);
+ SkOpSpan* markAndChaseWinding(const SkOpAngle* angle, const int winding);
+ SkOpSpan* markAndChaseWinding(int index, int endIndex, int winding, int oppWinding);
+ SkOpSpan* markAndChaseWinding(const SkOpAngle* angle, int winding, int oppWinding);
+ SkOpSpan* markAngle(int maxWinding, int sumWinding, bool activeAngle, const SkOpAngle* angle);
+ SkOpSpan* markAngle(int maxWinding, int sumWinding, int oppMaxWinding, int oppSumWinding,
+ bool activeAngle, const SkOpAngle* angle);
+ void markDone(int index, int winding);
+ void markDoneBinary(int index, int winding, int oppWinding);
+ void markDoneBinary(int index);
+ void markDoneUnary(int index, int winding);
+ void markDoneUnary(int index);
+ void markOneDone(const char* funName, int tIndex, int winding);
+ void markOneDoneBinary(const char* funName, int tIndex);
+ void markOneDoneBinary(const char* funName, int tIndex, int winding, int oppWinding);
+ void markOneDoneUnary(const char* funName, int tIndex);
+ void markOneDoneUnary(const char* funName, int tIndex, int winding);
+ SkOpSpan* markOneWinding(const char* funName, int tIndex, int winding);
+ SkOpSpan* markOneWinding(const char* funName, int tIndex, int winding, int oppWinding);
+ void markUnsortable(int start, int end);
+ void markWinding(int index, int winding);
+ void markWinding(int index, int winding, int oppWinding);
+ void matchWindingValue(int tIndex, double t, bool borrowWind);
+
+ bool monotonicInY(int tStart, int tEnd) const;
+ bool moreHorizontal(int index, int endIndex, bool& unsortable) const;
+ bool multipleSpans(int end) const;
+ bool nextCandidate(int& start, int& end) const;
+ SkOpSegment* nextChase(int& index, const int step, int& min, SkOpSpan*& last);
+ int nextExactSpan(int from, int step) const;
+ int nextSpan(int from, int step) const;
+ bool serpentine(int tStart, int tEnd) const;
+ void setUpWindings(int index, int endIndex, int& sumMiWinding, int& sumSuWinding,
+ int& maxWinding, int& sumWinding, int& oppMaxWinding, int& oppSumWinding);
+ static bool SortAngles(SkTDArray<SkOpAngle>& angles, SkTDArray<SkOpAngle*>& angleList);
+ void subDivide(int start, int end, SkPoint edge[4]) const;
+ void subDivideBounds(int start, int end, SkPathOpsBounds& bounds) const;
+ bool tiny(const SkOpAngle* angle) const;
+ static void TrackOutside(SkTDArray<double>& outsideTs, double end, double start);
+ void undoneSpan(int& start, int& end);
+ int updateOppWinding(int index, int endIndex) const;
+ int updateOppWinding(const SkOpAngle* angle) const;
+ int updateOppWindingReverse(const SkOpAngle* angle) const;
+ int updateWinding(int index, int endIndex) const;
+ int updateWinding(const SkOpAngle* angle) const;
+ int updateWindingReverse(const SkOpAngle* angle) const;
+ static bool UseInnerWinding(int outerWinding, int innerWinding);
+ SkOpSpan* verifyOneWinding(const char* funName, int tIndex);
+ SkOpSpan* verifyOneWindingU(const char* funName, int tIndex);
+ int windingAtT(double tHit, int tIndex, bool crossOpp, SkScalar& dx) const;
+ int windSum(const SkOpAngle* angle) const;
+ int windValue(const SkOpAngle* angle) const;
+ int windValueAt(double t) const;
+ void zeroCoincidentOpp(SkOpSpan* oTest, int index);
+ void zeroCoincidentOther(SkOpSpan* test, const double tRatio, const double oEndT, int oIndex);
+ void zeroSpan(SkOpSpan* span);
+
+#if DEBUG_WINDING
+ static char as_digit(int value) {
+ return value < 0 ? '?' : value <= 9 ? '0' + value : '+';
+ }
+#endif
+
+#if DEBUG_DUMP
+ int debugID() const {
+ return fID;
+ }
+#endif
+
+#if DEBUG_SWAP_TOP
+ bool controlsContainedByEnds(int tStart, int tEnd) const;
+#endif
+#if DEBUG_CONCIDENT
+ void debugAddTPair(double t, const SkOpSegment& other, double otherT) const;
+#endif
+#if DEBUG_ACTIVE_SPANS
+ void debugShowActiveSpans() const;
+#endif
+#if DEBUG_MARK_DONE || DEBUG_UNSORTABLE
+ void debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding);
+ void debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding, int oppWinding);
+#endif
+#if DEBUG_SORT || DEBUG_SWAP_TOP
+ void debugShowSort(const char* fun, const SkTDArray<SkOpAngle*>& angles, int first,
+ const int contourWinding, const int oppContourWinding) const;
+ void debugShowSort(const char* fun, const SkTDArray<SkOpAngle*>& angles, int first);
+#endif
+#if DEBUG_WINDING
+ void debugShowSums() const;
+#endif
+#if DEBUG_CONCIDENT
+ void debugShowTs() const;
+#endif
+#if DEBUG_SHOW_WINDING
+ int debugShowWindingValues(int slotCount, int ofInterest) const;
+#endif
+#if DEBUG_DUMP
+ void dump() const;
+#endif
+#if DEBUG_ACTIVE_SPANS
+ void validateActiveSpans() const;
+#endif
+
+private:
+ const SkPoint* fPts;
+ SkPathOpsBounds fBounds;
+ SkTDArray<SkOpSpan> fTs; // two or more (always includes t=0 t=1)
+ // OPTIMIZATION: could pack donespans, verb, operand, xor into 1 int-sized value
+ int fDoneSpans; // quick check that segment is finished
+ // OPTIMIZATION: force the following to be byte-sized
+ SkPath::Verb fVerb;
+ bool fOperand;
+ bool fXor; // set if original contour had even-odd fill
+ bool fOppXor; // set if opposite operand had even-odd fill
+#if DEBUG_DUMP
+ int fID;
+#endif
+};
+
+#endif
« no previous file with comments | « src/pathops/SkOpEdgeBuilder.cpp ('k') | src/pathops/SkOpSegment.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698