OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright 2013 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 SkOpContour_DEFINED |
| 8 #define SkOpContour_DEFINED |
| 9 |
| 10 #include "SkOpSegment.h" |
| 11 #include "SkTArray.h" |
| 12 |
| 13 class SkIntersections; |
| 14 class SkOpContour; |
| 15 class SkPathWriter; |
| 16 |
| 17 struct SkCoincidence { |
| 18 SkOpContour* fContours[2]; |
| 19 int fSegments[2]; |
| 20 double fTs[2][2]; |
| 21 SkPoint fPts[2]; |
| 22 }; |
| 23 |
| 24 class SkOpContour { |
| 25 public: |
| 26 SkOpContour() { |
| 27 reset(); |
| 28 #if DEBUG_DUMP |
| 29 fID = ++gContourID; |
| 30 #endif |
| 31 } |
| 32 |
| 33 bool operator<(const SkOpContour& rh) const { |
| 34 return fBounds.fTop == rh.fBounds.fTop |
| 35 ? fBounds.fLeft < rh.fBounds.fLeft |
| 36 : fBounds.fTop < rh.fBounds.fTop; |
| 37 } |
| 38 |
| 39 void addCoincident(int index, SkOpContour* other, int otherIndex, |
| 40 const SkIntersections& ts, bool swap); |
| 41 void addCoincidentPoints(); |
| 42 |
| 43 void addCross(const SkOpContour* crosser) { |
| 44 #ifdef DEBUG_CROSS |
| 45 for (int index = 0; index < fCrosses.count(); ++index) { |
| 46 SkASSERT(fCrosses[index] != crosser); |
| 47 } |
| 48 #endif |
| 49 *fCrosses.append() = crosser; |
| 50 } |
| 51 |
| 52 void addCubic(const SkPoint pts[4]) { |
| 53 fSegments.push_back().addCubic(pts, fOperand, fXor); |
| 54 fContainsCurves = fContainsCubics = true; |
| 55 } |
| 56 |
| 57 int addLine(const SkPoint pts[2]) { |
| 58 fSegments.push_back().addLine(pts, fOperand, fXor); |
| 59 return fSegments.count(); |
| 60 } |
| 61 |
| 62 void addOtherT(int segIndex, int tIndex, double otherT, int otherIndex) { |
| 63 fSegments[segIndex].addOtherT(tIndex, otherT, otherIndex); |
| 64 } |
| 65 |
| 66 int addQuad(const SkPoint pts[3]) { |
| 67 fSegments.push_back().addQuad(pts, fOperand, fXor); |
| 68 fContainsCurves = true; |
| 69 return fSegments.count(); |
| 70 } |
| 71 |
| 72 int addT(int segIndex, SkOpContour* other, int otherIndex, const SkPoint& pt
, double newT) { |
| 73 setContainsIntercepts(); |
| 74 return fSegments[segIndex].addT(&other->fSegments[otherIndex], pt, newT)
; |
| 75 } |
| 76 |
| 77 int addSelfT(int segIndex, SkOpContour* other, int otherIndex, const SkPoint
& pt, double newT) { |
| 78 setContainsIntercepts(); |
| 79 return fSegments[segIndex].addSelfT(&other->fSegments[otherIndex], pt, n
ewT); |
| 80 } |
| 81 |
| 82 int addUnsortableT(int segIndex, SkOpContour* other, int otherIndex, bool st
art, |
| 83 const SkPoint& pt, double newT) { |
| 84 return fSegments[segIndex].addUnsortableT(&other->fSegments[otherIndex],
start, pt, newT); |
| 85 } |
| 86 |
| 87 const SkPathOpsBounds& bounds() const { |
| 88 return fBounds; |
| 89 } |
| 90 |
| 91 void calcCoincidentWinding(); |
| 92 |
| 93 void complete() { |
| 94 setBounds(); |
| 95 fContainsIntercepts = false; |
| 96 } |
| 97 |
| 98 bool containsCubics() const { |
| 99 return fContainsCubics; |
| 100 } |
| 101 |
| 102 bool crosses(const SkOpContour* crosser) const { |
| 103 for (int index = 0; index < fCrosses.count(); ++index) { |
| 104 if (fCrosses[index] == crosser) { |
| 105 return true; |
| 106 } |
| 107 } |
| 108 return false; |
| 109 } |
| 110 |
| 111 bool done() const { |
| 112 return fDone; |
| 113 } |
| 114 |
| 115 const SkPoint& end() const { |
| 116 const SkOpSegment& segment = fSegments.back(); |
| 117 return segment.pts()[segment.verb()]; |
| 118 } |
| 119 |
| 120 void findTooCloseToCall() { |
| 121 int segmentCount = fSegments.count(); |
| 122 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { |
| 123 fSegments[sIndex].findTooCloseToCall(); |
| 124 } |
| 125 } |
| 126 |
| 127 void fixOtherTIndex() { |
| 128 int segmentCount = fSegments.count(); |
| 129 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { |
| 130 fSegments[sIndex].fixOtherTIndex(); |
| 131 } |
| 132 } |
| 133 |
| 134 SkOpSegment* nonVerticalSegment(int& start, int& end); |
| 135 |
| 136 bool operand() const { |
| 137 return fOperand; |
| 138 } |
| 139 |
| 140 void reset() { |
| 141 fSegments.reset(); |
| 142 fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax); |
| 143 fContainsCurves = fContainsCubics = fContainsIntercepts = fDone = false; |
| 144 } |
| 145 |
| 146 void resolveCoincidence(SkTDArray<SkOpContour*>& contourList); |
| 147 |
| 148 SkTArray<SkOpSegment>& segments() { |
| 149 return fSegments; |
| 150 } |
| 151 |
| 152 void setContainsIntercepts() { |
| 153 fContainsIntercepts = true; |
| 154 } |
| 155 |
| 156 void setOperand(bool isOp) { |
| 157 fOperand = isOp; |
| 158 } |
| 159 |
| 160 void setOppXor(bool isOppXor) { |
| 161 fOppXor = isOppXor; |
| 162 int segmentCount = fSegments.count(); |
| 163 for (int test = 0; test < segmentCount; ++test) { |
| 164 fSegments[test].setOppXor(isOppXor); |
| 165 } |
| 166 } |
| 167 |
| 168 void setXor(bool isXor) { |
| 169 fXor = isXor; |
| 170 } |
| 171 |
| 172 void sortSegments(); |
| 173 |
| 174 const SkPoint& start() const { |
| 175 return fSegments.front().pts()[0]; |
| 176 } |
| 177 |
| 178 void toPath(SkPathWriter& path) const; |
| 179 |
| 180 void toPartialBackward(SkPathWriter& path) const { |
| 181 int segmentCount = fSegments.count(); |
| 182 for (int test = segmentCount - 1; test >= 0; --test) { |
| 183 fSegments[test].addCurveTo(1, 0, path, true); |
| 184 } |
| 185 } |
| 186 |
| 187 void toPartialForward(SkPathWriter& path) const { |
| 188 int segmentCount = fSegments.count(); |
| 189 for (int test = 0; test < segmentCount; ++test) { |
| 190 fSegments[test].addCurveTo(0, 1, path, true); |
| 191 } |
| 192 } |
| 193 |
| 194 void topSortableSegment(const SkPoint& topLeft, SkPoint& bestXY, SkOpSegment
*& topStart); |
| 195 SkOpSegment* undoneSegment(int& start, int& end); |
| 196 |
| 197 int updateSegment(int index, const SkPoint* pts) { |
| 198 SkOpSegment& segment = fSegments[index]; |
| 199 segment.updatePts(pts); |
| 200 return segment.verb() + 1; |
| 201 } |
| 202 |
| 203 #if DEBUG_TEST |
| 204 SkTArray<SkOpSegment>& debugSegments() { |
| 205 return fSegments; |
| 206 } |
| 207 #endif |
| 208 |
| 209 #if DEBUG_DUMP |
| 210 void dump(); |
| 211 #endif |
| 212 |
| 213 #if DEBUG_ACTIVE_SPANS |
| 214 void debugShowActiveSpans() { |
| 215 for (int index = 0; index < fSegments.count(); ++index) { |
| 216 fSegments[index].debugShowActiveSpans(); |
| 217 } |
| 218 } |
| 219 |
| 220 void validateActiveSpans() { |
| 221 for (int index = 0; index < fSegments.count(); ++index) { |
| 222 fSegments[index].validateActiveSpans(); |
| 223 } |
| 224 } |
| 225 #endif |
| 226 |
| 227 #if DEBUG_SHOW_WINDING |
| 228 int debugShowWindingValues(int totalSegments, int ofInterest); |
| 229 static void debugShowWindingValues(SkTDArray<SkOpContour*>& contourList); |
| 230 #endif |
| 231 |
| 232 private: |
| 233 void setBounds(); |
| 234 |
| 235 SkTArray<SkOpSegment> fSegments; |
| 236 SkTDArray<SkOpSegment*> fSortedSegments; |
| 237 int fFirstSorted; |
| 238 SkTDArray<SkCoincidence> fCoincidences; |
| 239 SkTDArray<const SkOpContour*> fCrosses; |
| 240 SkPathOpsBounds fBounds; |
| 241 bool fContainsIntercepts; // FIXME: is this used by anybody? |
| 242 bool fContainsCubics; |
| 243 bool fContainsCurves; |
| 244 bool fDone; |
| 245 bool fOperand; // true for the second argument to a binary operator |
| 246 bool fXor; |
| 247 bool fOppXor; |
| 248 #if DEBUG_DUMP |
| 249 int fID; |
| 250 #endif |
| 251 }; |
| 252 |
| 253 #endif |
OLD | NEW |