| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 #include "SkAddIntersections.h" | 7 #include "SkAddIntersections.h" |
| 8 #include "SkOpEdgeBuilder.h" | 8 #include "SkOpEdgeBuilder.h" |
| 9 #include "SkPathOpsCommon.h" | 9 #include "SkPathOpsCommon.h" |
| 10 #include "SkPathWriter.h" | 10 #include "SkPathWriter.h" |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 return last->segment(); | 34 return last->segment(); |
| 35 } | 35 } |
| 36 if (done) { | 36 if (done) { |
| 37 continue; | 37 continue; |
| 38 } | 38 } |
| 39 if (!sortable) { | 39 if (!sortable) { |
| 40 continue; | 40 continue; |
| 41 } | 41 } |
| 42 // find first angle, initialize winding to computed fWindSum | 42 // find first angle, initialize winding to computed fWindSum |
| 43 const SkOpAngle* angle = segment->spanToAngle(*tIndex, *endIndex); | 43 const SkOpAngle* angle = segment->spanToAngle(*tIndex, *endIndex); |
| 44 if (!angle) { |
| 45 continue; |
| 46 } |
| 44 const SkOpAngle* firstAngle = angle; | 47 const SkOpAngle* firstAngle = angle; |
| 45 SkDEBUGCODE(bool loop = false); | 48 SkDEBUGCODE(bool loop = false); |
| 46 int winding; | 49 int winding; |
| 47 do { | 50 do { |
| 48 angle = angle->next(); | 51 angle = angle->next(); |
| 49 SkASSERT(angle != firstAngle || !loop); | 52 SkASSERT(angle != firstAngle || !loop); |
| 50 SkDEBUGCODE(loop |= angle == firstAngle); | 53 SkDEBUGCODE(loop |= angle == firstAngle); |
| 51 segment = angle->segment(); | 54 segment = angle->segment(); |
| 52 winding = segment->windSum(angle); | 55 winding = segment->windSum(angle); |
| 53 } while (winding == SK_MinS32); | 56 } while (winding == SK_MinS32); |
| 54 int sumMiWinding = segment->updateWindingReverse(angle); | 57 int sumMiWinding = segment->updateWindingReverse(angle); |
| 55 int sumSuWinding = segment->updateOppWindingReverse(angle); | 58 int sumSuWinding = segment->updateOppWindingReverse(angle); |
| 56 if (segment->operand()) { | 59 if (segment->operand()) { |
| 57 SkTSwap<int>(sumMiWinding, sumSuWinding); | 60 SkTSwap<int>(sumMiWinding, sumSuWinding); |
| 58 } | 61 } |
| 59 SkOpSegment* first = NULL; | 62 SkOpSegment* first = NULL; |
| 60 while ((angle = angle->next()) != firstAngle) { | 63 while ((angle = angle->next()) != firstAngle) { |
| 61 segment = angle->segment(); | 64 segment = angle->segment(); |
| 62 int start = angle->start(); | 65 int start = angle->start(); |
| 63 int end = angle->end(); | 66 int end = angle->end(); |
| 64 int maxWinding, sumWinding, oppMaxWinding, oppSumWinding; | 67 int maxWinding, sumWinding, oppMaxWinding, oppSumWinding; |
| 65 segment->setUpWindings(start, end, &sumMiWinding, &sumSuWinding, | 68 segment->setUpWindings(start, end, &sumMiWinding, &sumSuWinding, |
| 66 &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding); | 69 &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding); |
| 67 if (!segment->done(angle)) { | 70 if (!segment->done(angle)) { |
| 68 if (!first) { | 71 if (!first) { |
| 69 first = segment; | 72 first = segment; |
| 70 *tIndex = start; | 73 *tIndex = start; |
| 71 *endIndex = end; | 74 *endIndex = end; |
| 72 } | 75 } |
| 76 // OPTIMIZATION: should this also add to the chase? |
| 73 (void) segment->markAngle(maxWinding, sumWinding, oppMaxWinding, | 77 (void) segment->markAngle(maxWinding, sumWinding, oppMaxWinding, |
| 74 oppSumWinding, angle); | 78 oppSumWinding, angle); |
| 75 } | 79 } |
| 76 } | 80 } |
| 77 if (first) { | 81 if (first) { |
| 78 #if TRY_ROTATE | 82 #if TRY_ROTATE |
| 79 *chase.insert(0) = span; | 83 *chase.insert(0) = span; |
| 80 #else | 84 #else |
| 81 *chase.append() = span; | 85 *chase.append() = span; |
| 82 #endif | 86 #endif |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 const int xorMask, const int xorOpMask, SkPathWriter* simple) { | 122 const int xorMask, const int xorOpMask, SkPathWriter* simple) { |
| 119 bool firstContour = true; | 123 bool firstContour = true; |
| 120 bool unsortable = false; | 124 bool unsortable = false; |
| 121 bool topUnsortable = false; | 125 bool topUnsortable = false; |
| 122 bool firstPass = true; | 126 bool firstPass = true; |
| 123 SkPoint lastTopLeft; | 127 SkPoint lastTopLeft; |
| 124 SkPoint topLeft = {SK_ScalarMin, SK_ScalarMin}; | 128 SkPoint topLeft = {SK_ScalarMin, SK_ScalarMin}; |
| 125 do { | 129 do { |
| 126 int index, endIndex; | 130 int index, endIndex; |
| 127 bool topDone; | 131 bool topDone; |
| 132 bool onlyVertical = false; |
| 128 lastTopLeft = topLeft; | 133 lastTopLeft = topLeft; |
| 129 SkOpSegment* current = FindSortableTop(contourList, SkOpAngle::kBinarySi
ngle, &firstContour, | 134 SkOpSegment* current = FindSortableTop(contourList, SkOpAngle::kBinarySi
ngle, &firstContour, |
| 130 &index, &endIndex, &topLeft, &topUnsortable, &topDone, firstPass
); | 135 &index, &endIndex, &topLeft, &topUnsortable, &topDone, &onlyVert
ical, firstPass); |
| 131 if (!current) { | 136 if (!current) { |
| 132 if ((!topUnsortable || firstPass) && !topDone) { | 137 if ((!topUnsortable || firstPass) && !topDone) { |
| 133 SkASSERT(topLeft.fX != SK_ScalarMin && topLeft.fY != SK_ScalarMi
n); | 138 SkASSERT(topLeft.fX != SK_ScalarMin && topLeft.fY != SK_ScalarMi
n); |
| 134 if (lastTopLeft.fX == SK_ScalarMin && lastTopLeft.fY == SK_Scala
rMin) { | 139 if (lastTopLeft.fX == SK_ScalarMin && lastTopLeft.fY == SK_Scala
rMin) { |
| 135 if (firstPass) { | 140 if (firstPass) { |
| 136 firstPass = false; | 141 firstPass = false; |
| 137 } else { | 142 } else { |
| 138 break; | 143 break; |
| 139 } | 144 } |
| 140 } | 145 } |
| 141 topLeft.fX = topLeft.fY = SK_ScalarMin; | 146 topLeft.fX = topLeft.fY = SK_ScalarMin; |
| 142 continue; | 147 continue; |
| 143 } | 148 } |
| 144 break; | 149 break; |
| 150 } else if (onlyVertical) { |
| 151 break; |
| 145 } | 152 } |
| 146 firstPass = !topUnsortable || lastTopLeft != topLeft; | 153 firstPass = !topUnsortable || lastTopLeft != topLeft; |
| 147 SkTDArray<SkOpSpan*> chaseArray; | 154 SkTDArray<SkOpSpan*> chase; |
| 148 do { | 155 do { |
| 149 if (current->activeOp(index, endIndex, xorMask, xorOpMask, op)) { | 156 if (current->activeOp(index, endIndex, xorMask, xorOpMask, op)) { |
| 150 do { | 157 do { |
| 151 if (!unsortable && current->done()) { | 158 if (!unsortable && current->done()) { |
| 152 if (simple->isEmpty()) { | |
| 153 simple->init(); | |
| 154 } | |
| 155 break; | 159 break; |
| 156 } | 160 } |
| 157 SkASSERT(unsortable || !current->done()); | 161 SkASSERT(unsortable || !current->done()); |
| 158 int nextStart = index; | 162 int nextStart = index; |
| 159 int nextEnd = endIndex; | 163 int nextEnd = endIndex; |
| 160 SkOpSegment* next = current->findNextOp(&chaseArray, &nextSt
art, &nextEnd, | 164 SkOpSegment* next = current->findNextOp(&chase, &nextStart,
&nextEnd, |
| 161 &unsortable, op, xorMask, xorOpMask); | 165 &unsortable, op, xorMask, xorOpMask); |
| 162 if (!next) { | 166 if (!next) { |
| 163 if (!unsortable && simple->hasMove() | 167 if (!unsortable && simple->hasMove() |
| 164 && current->verb() != SkPath::kLine_Verb | 168 && current->verb() != SkPath::kLine_Verb |
| 165 && !simple->isClosed()) { | 169 && !simple->isClosed()) { |
| 166 current->addCurveTo(index, endIndex, simple, true); | 170 current->addCurveTo(index, endIndex, simple, true); |
| 167 SkASSERT(simple->isClosed()); | 171 #if DEBUG_ACTIVE_SPANS |
| 172 if (!simple->isClosed()) { |
| 173 DebugShowActiveSpans(contourList); |
| 174 } |
| 175 #endif |
| 176 // SkASSERT(simple->isClosed()); |
| 168 } | 177 } |
| 169 break; | 178 break; |
| 170 } | 179 } |
| 171 #if DEBUG_FLOW | 180 #if DEBUG_FLOW |
| 172 SkDebugf("%s current id=%d from=(%1.9g,%1.9g) to=(%1.9g,%1.9g)\n", _
_FUNCTION__, | 181 SkDebugf("%s current id=%d from=(%1.9g,%1.9g) to=(%1.9g,%1.9g)\n", _
_FUNCTION__, |
| 173 current->debugID(), current->xyAtT(index).fX, current->xyAtT
(index).fY, | 182 current->debugID(), current->xyAtT(index).fX, current->xyAtT
(index).fY, |
| 174 current->xyAtT(endIndex).fX, current->xyAtT(endIndex).fY); | 183 current->xyAtT(endIndex).fX, current->xyAtT(endIndex).fY); |
| 175 #endif | 184 #endif |
| 176 current->addCurveTo(index, endIndex, simple, true); | 185 current->addCurveTo(index, endIndex, simple, true); |
| 177 current = next; | 186 current = next; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 188 if (!current->done(min)) { | 197 if (!current->done(min)) { |
| 189 current->addCurveTo(index, endIndex, simple, true); | 198 current->addCurveTo(index, endIndex, simple, true); |
| 190 current->markDoneBinary(min); | 199 current->markDoneBinary(min); |
| 191 } | 200 } |
| 192 } | 201 } |
| 193 simple->close(); | 202 simple->close(); |
| 194 } else { | 203 } else { |
| 195 SkOpSpan* last = current->markAndChaseDoneBinary(index, endIndex
); | 204 SkOpSpan* last = current->markAndChaseDoneBinary(index, endIndex
); |
| 196 if (last && !last->fChased && !last->fLoop) { | 205 if (last && !last->fChased && !last->fLoop) { |
| 197 last->fChased = true; | 206 last->fChased = true; |
| 198 SkASSERT(!SkPathOpsDebug::ChaseContains(chaseArray, last)); | 207 SkASSERT(!SkPathOpsDebug::ChaseContains(chase, last)); |
| 199 *chaseArray.append() = last; | 208 *chase.append() = last; |
| 209 #if DEBUG_WINDING |
| 210 SkDebugf("%s chase.append id=%d windSum=%d small=%d\n", __FU
NCTION__, |
| 211 last->fOther->span(last->fOtherIndex).fOther->debugI
D(), last->fWindSum, |
| 212 last->fSmall); |
| 213 #endif |
| 200 } | 214 } |
| 201 } | 215 } |
| 202 current = findChaseOp(chaseArray, &index, &endIndex); | 216 current = findChaseOp(chase, &index, &endIndex); |
| 203 #if DEBUG_ACTIVE_SPANS | 217 #if DEBUG_ACTIVE_SPANS |
| 204 DebugShowActiveSpans(contourList); | 218 DebugShowActiveSpans(contourList); |
| 205 #endif | 219 #endif |
| 206 if (!current) { | 220 if (!current) { |
| 207 break; | 221 break; |
| 208 } | 222 } |
| 209 } while (true); | 223 } while (true); |
| 210 } while (true); | 224 } while (true); |
| 211 return simple->someAssemblyRequired(); | 225 return simple->someAssemblyRequired(); |
| 212 } | 226 } |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 300 { // if some edges could not be resolved, assemble remaining fragments | 314 { // if some edges could not be resolved, assemble remaining fragments |
| 301 SkPath temp; | 315 SkPath temp; |
| 302 temp.setFillType(fillType); | 316 temp.setFillType(fillType); |
| 303 SkPathWriter assembled(temp); | 317 SkPathWriter assembled(temp); |
| 304 Assemble(wrapper, &assembled); | 318 Assemble(wrapper, &assembled); |
| 305 *result = *assembled.nativePath(); | 319 *result = *assembled.nativePath(); |
| 306 result->setFillType(fillType); | 320 result->setFillType(fillType); |
| 307 } | 321 } |
| 308 return true; | 322 return true; |
| 309 } | 323 } |
| OLD | NEW |