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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/pathops/SkOpEdgeBuilder.cpp ('k') | src/pathops/SkOpSegment.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7 #ifndef SkOpSegment_DEFINE
8 #define SkOpSegment_DEFINE
9
10 #include "SkOpAngle.h"
11 #include "SkPathOpsBounds.h"
12 #include "SkPathOpsCurve.h"
13 #include "SkTDArray.h"
14
15 class SkPathWriter;
16
17 class SkOpSegment {
18 public:
19 SkOpSegment() {
20 #if DEBUG_DUMP
21 fID = ++gSegmentID;
22 #endif
23 }
24
25 bool operator<(const SkOpSegment& rh) const {
26 return fBounds.fTop < rh.fBounds.fTop;
27 }
28
29 const SkPathOpsBounds& bounds() const {
30 return fBounds;
31 }
32
33 // OPTIMIZE
34 // when the edges are initially walked, they don't automatically get the pri or and next
35 // edges assigned to positions t=0 and t=1. Doing that would remove the need for this check,
36 // and would additionally remove the need for similar checks in condition ed ges. It would
37 // also allow intersection code to assume end of segment intersections (mayb e?)
38 bool complete() const {
39 int count = fTs.count();
40 return count > 1 && fTs[0].fT == 0 && fTs[--count].fT == 1;
41 }
42
43 bool done() const {
44 SkASSERT(fDoneSpans <= fTs.count());
45 return fDoneSpans == fTs.count();
46 }
47
48 bool done(int min) const {
49 return fTs[min].fDone;
50 }
51
52 bool done(const SkOpAngle* angle) const {
53 return done(SkMin32(angle->start(), angle->end()));
54 }
55
56 SkVector dxdy(int index) const {
57 return (*CurveSlopeAtT[fVerb])(fPts, fTs[index].fT);
58 }
59
60 SkScalar dy(int index) const {
61 return dxdy(index).fY;
62 }
63
64 bool intersected() const {
65 return fTs.count() > 0;
66 }
67
68 bool isCanceled(int tIndex) const {
69 return fTs[tIndex].fWindValue == 0 && fTs[tIndex].fOppValue == 0;
70 }
71
72 bool isConnected(int startIndex, int endIndex) const {
73 return fTs[startIndex].fWindSum != SK_MinS32 || fTs[endIndex].fWindSum ! = SK_MinS32;
74 }
75
76 bool isHorizontal() const {
77 return fBounds.fTop == fBounds.fBottom;
78 }
79
80 bool isVertical() const {
81 return fBounds.fLeft == fBounds.fRight;
82 }
83
84 bool isVertical(int start, int end) const {
85 return (*CurveIsVertical[fVerb])(fPts, start, end);
86 }
87
88 bool operand() const {
89 return fOperand;
90 }
91
92 int oppSign(const SkOpAngle* angle) const {
93 SkASSERT(angle->segment() == this);
94 return oppSign(angle->start(), angle->end());
95 }
96
97 int oppSign(int startIndex, int endIndex) const {
98 int result = startIndex < endIndex ? -fTs[startIndex].fOppValue : fTs[en dIndex].fOppValue;
99 #if DEBUG_WIND_BUMP
100 SkDebugf("%s oppSign=%d\n", __FUNCTION__, result);
101 #endif
102 return result;
103 }
104
105 int oppSum(int tIndex) const {
106 return fTs[tIndex].fOppSum;
107 }
108
109 int oppSum(const SkOpAngle* angle) const {
110 int lesser = SkMin32(angle->start(), angle->end());
111 return fTs[lesser].fOppSum;
112 }
113
114 int oppValue(int tIndex) const {
115 return fTs[tIndex].fOppValue;
116 }
117
118 int oppValue(const SkOpAngle* angle) const {
119 int lesser = SkMin32(angle->start(), angle->end());
120 return fTs[lesser].fOppValue;
121 }
122
123 const SkPoint* pts() const {
124 return fPts;
125 }
126
127 void reset() {
128 init(NULL, (SkPath::Verb) -1, false, false);
129 fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax);
130 fTs.reset();
131 }
132
133 void setOppXor(bool isOppXor) {
134 fOppXor = isOppXor;
135 }
136
137 void setSpanT(int index, double t) {
138 SkOpSpan& span = fTs[index];
139 span.fT = t;
140 span.fOther->fTs[span.fOtherIndex].fOtherT = t;
141 }
142
143 void setUpWinding(int index, int endIndex, int& maxWinding, int& sumWinding) {
144 int deltaSum = spanSign(index, endIndex);
145 maxWinding = sumWinding;
146 sumWinding = sumWinding -= deltaSum;
147 }
148
149 // OPTIMIZATION: mark as debugging only if used solely by tests
150 const SkOpSpan& span(int tIndex) const {
151 return fTs[tIndex];
152 }
153
154 int spanSign(const SkOpAngle* angle) const {
155 SkASSERT(angle->segment() == this);
156 return spanSign(angle->start(), angle->end());
157 }
158
159 int spanSign(int startIndex, int endIndex) const {
160 int result = startIndex < endIndex ? -fTs[startIndex].fWindValue : fTs[e ndIndex].fWindValue;
161 #if DEBUG_WIND_BUMP
162 SkDebugf("%s spanSign=%d\n", __FUNCTION__, result);
163 #endif
164 return result;
165 }
166
167 // OPTIMIZATION: mark as debugging only if used solely by tests
168 double t(int tIndex) const {
169 return fTs[tIndex].fT;
170 }
171
172 double tAtMid(int start, int end, double mid) const {
173 return fTs[start].fT * (1 - mid) + fTs[end].fT * mid;
174 }
175
176 bool unsortable(int index) const {
177 return fTs[index].fUnsortableStart || fTs[index].fUnsortableEnd;
178 }
179
180 void updatePts(const SkPoint pts[]) {
181 fPts = pts;
182 }
183
184 SkPath::Verb verb() const {
185 return fVerb;
186 }
187
188 int windSum(int tIndex) const {
189 return fTs[tIndex].fWindSum;
190 }
191
192 int windValue(int tIndex) const {
193 return fTs[tIndex].fWindValue;
194 }
195
196 SkScalar xAtT(int index) const {
197 return xAtT(&fTs[index]);
198 }
199
200 SkScalar xAtT(const SkOpSpan* span) const {
201 return xyAtT(span).fX;
202 }
203
204 const SkPoint& xyAtT(const SkOpSpan* span) const {
205 return span->fPt;
206 }
207
208 // used only by right angle winding finding
209 SkPoint xyAtT(double mid) const {
210 return (*CurvePointAtT[fVerb])(fPts, mid);
211 }
212
213 const SkPoint& xyAtT(int index) const {
214 return xyAtT(&fTs[index]);
215 }
216
217 SkScalar yAtT(int index) const {
218 return yAtT(&fTs[index]);
219 }
220
221 SkScalar yAtT(const SkOpSpan* span) const {
222 return xyAtT(span).fY;
223 }
224
225 bool activeAngle(int index, int& done, SkTDArray<SkOpAngle>& angles);
226 bool activeAngleOther(int index, int& done, SkTDArray<SkOpAngle>& angles);
227 bool activeAngleInner(int index, int& done, SkTDArray<SkOpAngle>& angles);
228 SkPoint activeLeftTop(bool onlySortable, int* firstT) const;
229 bool activeOp(int index, int endIndex, int xorMiMask, int xorSuMask, SkPathO p op);
230 bool activeOp(int xorMiMask, int xorSuMask, int index, int endIndex, SkPathO p op,
231 int& sumMiWinding, int& sumSuWinding, int& maxWinding, int& su mWinding,
232 int& oppMaxWinding, int& oppSumWinding);
233 bool activeWinding(int index, int endIndex);
234 bool activeWinding(int index, int endIndex, int& maxWinding, int& sumWinding );
235 void addAngle(SkTDArray<SkOpAngle>& angles, int start, int end) const;
236 void addCancelOutsides(double tStart, double oStart, SkOpSegment& other, dou ble oEnd);
237 void addCoinOutsides(const SkTDArray<double>& outsideTs, SkOpSegment& other, double oEnd);
238 void addCubic(const SkPoint pts[4], bool operand, bool evenOdd);
239 void addCurveTo(int start, int end, SkPathWriter& path, bool active) const;
240 void addLine(const SkPoint pts[2], bool operand, bool evenOdd);
241 void addOtherT(int index, double otherT, int otherIndex);
242 void addQuad(const SkPoint pts[3], bool operand, bool evenOdd);
243 int addSelfT(SkOpSegment* other, const SkPoint& pt, double newT);
244 int addT(SkOpSegment* other, const SkPoint& pt, double newT);
245 void addTCancel(double startT, double endT, SkOpSegment& other, double oStar tT, double oEndT);
246 void addTCoincident(double startT, double endT, SkOpSegment& other, double o StartT,
247 double oEndT);
248 void addTPair(double t, SkOpSegment& other, double otherT, bool borrowWind, const SkPoint& pt);
249 void addTwoAngles(int start, int end, SkTDArray<SkOpAngle>& angles) const;
250
251 int addUnsortableT(SkOpSegment* other, bool start, const SkPoint& pt, double newT);
252 int advanceCoincidentOther(const SkOpSpan* test, double oEndT, int& oIndex);
253 int advanceCoincidentThis(const SkOpSpan* oTest, bool opp, int index);
254 bool betweenTs(int lesser, double testT, int greater);
255 void buildAngles(int index, SkTDArray<SkOpAngle>& angles, bool includeOpp) c onst;
256 void buildAnglesInner(int index, SkTDArray<SkOpAngle>& angles) const;
257 int bumpCoincidentThis(const SkOpSpan* oTest, bool opp, int index,
258 SkTDArray<double>& outsideTs);
259 int bumpCoincidentOther(const SkOpSpan* test, double oEndT, int& oIndex,
260 SkTDArray<double>& oOutsideTs);
261 bool bumpSpan(SkOpSpan* span, int windDelta, int oppDelta);
262 bool clockwise(int tStart, int tEnd) const;
263 int computeSum(int startIndex, int endIndex, bool binary);
264 int crossedSpanY(const SkPoint& basePt, SkScalar& bestY, double& hitT, bool& hitSomething,
265 double mid, bool opp, bool current) const;
266 void decrementSpan(SkOpSpan* span);
267 bool equalPoints(int greaterTIndex, int lesserTIndex);
268 SkOpSegment* findNextOp(SkTDArray<SkOpSpan*>& chase, int& nextStart, int& ne xtEnd,
269 bool& unsortable, SkPathOp op, const int xorMiMask,
270 const int xorSuMask);
271 int findStartingEdge(SkTDArray<SkOpAngle*>& sorted, int start, int end);
272 SkOpSegment* findNextWinding(SkTDArray<SkOpSpan*>& chase, int& nextStart, in t& nextEnd,
273 bool& unsortable);
274 SkOpSegment* findNextXor(int& nextStart, int& nextEnd, bool& unsortable);
275 void findTooCloseToCall();
276 SkOpSegment* findTop(int& tIndex, int& endIndex, bool& unsortable, bool only Sortable);
277 void fixOtherTIndex();
278 void init(const SkPoint pts[], SkPath::Verb verb, bool operand, bool evenOdd );
279 void initWinding(int start, int end);
280 void initWinding(int start, int end, int winding, int oppWinding);
281 void initWinding(int start, int end, double tHit, int winding, SkScalar hitD x, int oppWind,
282 SkScalar hitOppDx);
283 bool isLinear(int start, int end) const;
284 bool isMissing(double startT) const;
285 bool isSimple(int end) const;
286 SkOpSpan* markAndChaseDone(const SkOpAngle* angle, int winding);
287 SkOpSpan* markAndChaseDone(int index, int endIndex, int winding);
288 SkOpSpan* markAndChaseDoneBinary(const SkOpAngle* angle, int winding, int op pWinding);
289 SkOpSpan* markAndChaseDoneBinary(int index, int endIndex);
290 SkOpSpan* markAndChaseDoneUnary(int index, int endIndex);
291 SkOpSpan* markAndChaseDoneUnary(const SkOpAngle* angle, int winding);
292 SkOpSpan* markAndChaseWinding(const SkOpAngle* angle, const int winding);
293 SkOpSpan* markAndChaseWinding(int index, int endIndex, int winding, int oppW inding);
294 SkOpSpan* markAndChaseWinding(const SkOpAngle* angle, int winding, int oppWi nding);
295 SkOpSpan* markAngle(int maxWinding, int sumWinding, bool activeAngle, const SkOpAngle* angle);
296 SkOpSpan* markAngle(int maxWinding, int sumWinding, int oppMaxWinding, int o ppSumWinding,
297 bool activeAngle, const SkOpAngle* angle);
298 void markDone(int index, int winding);
299 void markDoneBinary(int index, int winding, int oppWinding);
300 void markDoneBinary(int index);
301 void markDoneUnary(int index, int winding);
302 void markDoneUnary(int index);
303 void markOneDone(const char* funName, int tIndex, int winding);
304 void markOneDoneBinary(const char* funName, int tIndex);
305 void markOneDoneBinary(const char* funName, int tIndex, int winding, int opp Winding);
306 void markOneDoneUnary(const char* funName, int tIndex);
307 void markOneDoneUnary(const char* funName, int tIndex, int winding);
308 SkOpSpan* markOneWinding(const char* funName, int tIndex, int winding);
309 SkOpSpan* markOneWinding(const char* funName, int tIndex, int winding, int o ppWinding);
310 void markUnsortable(int start, int end);
311 void markWinding(int index, int winding);
312 void markWinding(int index, int winding, int oppWinding);
313 void matchWindingValue(int tIndex, double t, bool borrowWind);
314
315 bool monotonicInY(int tStart, int tEnd) const;
316 bool moreHorizontal(int index, int endIndex, bool& unsortable) const;
317 bool multipleSpans(int end) const;
318 bool nextCandidate(int& start, int& end) const;
319 SkOpSegment* nextChase(int& index, const int step, int& min, SkOpSpan*& last );
320 int nextExactSpan(int from, int step) const;
321 int nextSpan(int from, int step) const;
322 bool serpentine(int tStart, int tEnd) const;
323 void setUpWindings(int index, int endIndex, int& sumMiWinding, int& sumSuWin ding,
324 int& maxWinding, int& sumWinding, int& oppMaxWinding, int& oppSumWin ding);
325 static bool SortAngles(SkTDArray<SkOpAngle>& angles, SkTDArray<SkOpAngle*>& angleList);
326 void subDivide(int start, int end, SkPoint edge[4]) const;
327 void subDivideBounds(int start, int end, SkPathOpsBounds& bounds) const;
328 bool tiny(const SkOpAngle* angle) const;
329 static void TrackOutside(SkTDArray<double>& outsideTs, double end, double st art);
330 void undoneSpan(int& start, int& end);
331 int updateOppWinding(int index, int endIndex) const;
332 int updateOppWinding(const SkOpAngle* angle) const;
333 int updateOppWindingReverse(const SkOpAngle* angle) const;
334 int updateWinding(int index, int endIndex) const;
335 int updateWinding(const SkOpAngle* angle) const;
336 int updateWindingReverse(const SkOpAngle* angle) const;
337 static bool UseInnerWinding(int outerWinding, int innerWinding);
338 SkOpSpan* verifyOneWinding(const char* funName, int tIndex);
339 SkOpSpan* verifyOneWindingU(const char* funName, int tIndex);
340 int windingAtT(double tHit, int tIndex, bool crossOpp, SkScalar& dx) const;
341 int windSum(const SkOpAngle* angle) const;
342 int windValue(const SkOpAngle* angle) const;
343 int windValueAt(double t) const;
344 void zeroCoincidentOpp(SkOpSpan* oTest, int index);
345 void zeroCoincidentOther(SkOpSpan* test, const double tRatio, const double o EndT, int oIndex);
346 void zeroSpan(SkOpSpan* span);
347
348 #if DEBUG_WINDING
349 static char as_digit(int value) {
350 return value < 0 ? '?' : value <= 9 ? '0' + value : '+';
351 }
352 #endif
353
354 #if DEBUG_DUMP
355 int debugID() const {
356 return fID;
357 }
358 #endif
359
360 #if DEBUG_SWAP_TOP
361 bool controlsContainedByEnds(int tStart, int tEnd) const;
362 #endif
363 #if DEBUG_CONCIDENT
364 void debugAddTPair(double t, const SkOpSegment& other, double otherT) const ;
365 #endif
366 #if DEBUG_ACTIVE_SPANS
367 void debugShowActiveSpans() const;
368 #endif
369 #if DEBUG_MARK_DONE || DEBUG_UNSORTABLE
370 void debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding) ;
371 void debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding, int oppWinding);
372 #endif
373 #if DEBUG_SORT || DEBUG_SWAP_TOP
374 void debugShowSort(const char* fun, const SkTDArray<SkOpAngle*>& angles, int first,
375 const int contourWinding, const int oppContourWinding) const;
376 void debugShowSort(const char* fun, const SkTDArray<SkOpAngle*>& angles, int first);
377 #endif
378 #if DEBUG_WINDING
379 void debugShowSums() const;
380 #endif
381 #if DEBUG_CONCIDENT
382 void debugShowTs() const;
383 #endif
384 #if DEBUG_SHOW_WINDING
385 int debugShowWindingValues(int slotCount, int ofInterest) const;
386 #endif
387 #if DEBUG_DUMP
388 void dump() const;
389 #endif
390 #if DEBUG_ACTIVE_SPANS
391 void validateActiveSpans() const;
392 #endif
393
394 private:
395 const SkPoint* fPts;
396 SkPathOpsBounds fBounds;
397 SkTDArray<SkOpSpan> fTs; // two or more (always includes t=0 t=1)
398 // OPTIMIZATION: could pack donespans, verb, operand, xor into 1 int-sized v alue
399 int fDoneSpans; // quick check that segment is finished
400 // OPTIMIZATION: force the following to be byte-sized
401 SkPath::Verb fVerb;
402 bool fOperand;
403 bool fXor; // set if original contour had even-odd fill
404 bool fOppXor; // set if opposite operand had even-odd fill
405 #if DEBUG_DUMP
406 int fID;
407 #endif
408 };
409
410 #endif
OLDNEW
« 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