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.push_back(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, newT); 80 } 81 82 int addUnsortableT(int segIndex, SkOpContour* other, int otherIndex, bool start, 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 checkEnds() { 94 if (!fContainsCurves) { 95 return; 96 } 97 int segmentCount = fSegments.count(); 98 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { 99 SkOpSegment* segment = &fSegments[sIndex]; 100 if (segment->verb() == SkPath::kLine_Verb) { 101 continue; 102 } 103 fSegments[sIndex].checkEnds(); 104 } 105 } 106 107 void complete() { 108 setBounds(); 109 fContainsIntercepts = false; 110 } 111 112 bool containsCubics() const { 113 return fContainsCubics; 114 } 115 116 bool crosses(const SkOpContour* crosser) const { 117 for (int index = 0; index < fCrosses.count(); ++index) { 118 if (fCrosses[index] == crosser) { 119 return true; 120 } 121 } 122 return false; 123 } 124 125 bool done() const { 126 return fDone; 127 } 128 129 const SkPoint& end() const { 130 const SkOpSegment& segment = fSegments.back(); 131 return segment.pts()[SkPathOpsVerbToPoints(segment.verb())]; 132 } 133 134 void findTooCloseToCall() { 135 int segmentCount = fSegments.count(); 136 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { 137 fSegments[sIndex].findTooCloseToCall(); 138 } 139 } 140 141 void fixOtherTIndex() { 142 int segmentCount = fSegments.count(); 143 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { 144 fSegments[sIndex].fixOtherTIndex(); 145 } 146 } 147 148 SkOpSegment* nonVerticalSegment(int* start, int* end); 149 150 bool operand() const { 151 return fOperand; 152 } 153 154 void reset() { 155 fSegments.reset(); 156 fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax); 157 fContainsCurves = fContainsCubics = fContainsIntercepts = fDone = false; 158 } 159 160 SkTArray<SkOpSegment>& segments() { 161 return fSegments; 162 } 163 164 void setContainsIntercepts() { 165 fContainsIntercepts = true; 166 } 167 168 void setOperand(bool isOp) { 169 fOperand = isOp; 170 } 171 172 void setOppXor(bool isOppXor) { 173 fOppXor = isOppXor; 174 int segmentCount = fSegments.count(); 175 for (int test = 0; test < segmentCount; ++test) { 176 fSegments[test].setOppXor(isOppXor); 177 } 178 } 179 180 void setXor(bool isXor) { 181 fXor = isXor; 182 } 183 184 void sortSegments(); 185 186 const SkPoint& start() const { 187 return fSegments.front().pts()[0]; 188 } 189 190 void toPath(SkPathWriter* path) const; 191 192 void toPartialBackward(SkPathWriter* path) const { 193 int segmentCount = fSegments.count(); 194 for (int test = segmentCount - 1; test >= 0; --test) { 195 fSegments[test].addCurveTo(1, 0, path, true); 196 } 197 } 198 199 void toPartialForward(SkPathWriter* path) const { 200 int segmentCount = fSegments.count(); 201 for (int test = 0; test < segmentCount; ++test) { 202 fSegments[test].addCurveTo(0, 1, path, true); 203 } 204 } 205 206 void topSortableSegment(const SkPoint& topLeft, SkPoint* bestXY, SkOpSegment** topStart); 207 SkOpSegment* undoneSegment(int* start, int* end); 208 209 int updateSegment(int index, const SkPoint* pts) { 210 SkOpSegment& segment = fSegments[index]; 211 segment.updatePts(pts); 212 return SkPathOpsVerbToPoints(segment.verb()) + 1; 213 } 214 215 #if DEBUG_TEST 216 SkTArray<SkOpSegment>& debugSegments() { 217 return fSegments; 218 } 219 #endif 220 221 #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY 222 void debugShowActiveSpans() { 223 for (int index = 0; index < fSegments.count(); ++index) { 224 fSegments[index].debugShowActiveSpans(); 225 } 226 } 227 #endif 228 229 #if DEBUG_SHOW_WINDING 230 int debugShowWindingValues(int totalSegments, int ofInterest); 231 static void debugShowWindingValues(const SkTArray<SkOpContour*, true>& contourList); 232 #endif 233 234 private: 235 void setBounds(); 236 237 SkTArray<SkOpSegment> fSegments; 238 SkTArray<SkOpSegment*, true> fSortedSegments; 239 int fFirstSorted; 240 SkTArray<SkCoincidence, true> fCoincidences; 241 SkTArray<const SkOpContour*, true> fCrosses; 242 SkPathOpsBounds fBounds; 243 bool fContainsIntercepts; // FIXME: is this used by anybody? 244 bool fContainsCubics; 245 bool fContainsCurves; 246 bool fDone; 247 bool fOperand; // true for the second argument to a binary operator 248 bool fXor; 249 bool fOppXor; 250 #if DEBUG_DUMP 251 int fID; 252 #endif 253 }; 254 255 #endif 256