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 |