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" |
11 | 11 |
12 static SkOpSegment* findChaseOp(SkTDArray<SkOpSpan*>& chase, int* tIndex, int* e
ndIndex) { | 12 static SkOpSegment* findChaseOp(SkTDArray<SkOpSpan*>& chase, int* tIndex, int* e
ndIndex) { |
13 while (chase.count()) { | 13 while (chase.count()) { |
14 SkOpSpan* span; | 14 SkOpSpan* span; |
15 chase.pop(&span); | 15 chase.pop(&span); |
16 const SkOpSpan& backPtr = span->fOther->span(span->fOtherIndex); | 16 const SkOpSpan& backPtr = span->fOther->span(span->fOtherIndex); |
17 SkOpSegment* segment = backPtr.fOther; | 17 SkOpSegment* segment = backPtr.fOther; |
18 *tIndex = backPtr.fOtherIndex; | 18 *tIndex = backPtr.fOtherIndex; |
19 bool sortable = true; | 19 bool sortable = true; |
20 bool done = true; | 20 bool done = true; |
21 *endIndex = -1; | 21 *endIndex = -1; |
22 if (const SkOpAngle* last = segment->activeAngle(*tIndex, tIndex, endInd
ex, &done, | 22 if (const SkOpAngle* last = segment->activeAngle(*tIndex, tIndex, endInd
ex, &done, |
23 &sortable)) { | 23 &sortable)) { |
| 24 if (last->unorderable()) { |
| 25 continue; |
| 26 } |
24 *tIndex = last->start(); | 27 *tIndex = last->start(); |
25 *endIndex = last->end(); | 28 *endIndex = last->end(); |
26 #if TRY_ROTATE | 29 #if TRY_ROTATE |
27 *chase.insert(0) = span; | 30 *chase.insert(0) = span; |
28 #else | 31 #else |
29 *chase.append() = span; | 32 *chase.append() = span; |
30 #endif | 33 #endif |
31 return last->segment(); | 34 return last->segment(); |
32 } | 35 } |
33 if (done) { | 36 if (done) { |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 bool opActive = oppWinding != 0; | 112 bool opActive = oppWinding != 0; |
110 return gOpLookup[op][opActive][windingIsOp]; | 113 return gOpLookup[op][opActive][windingIsOp]; |
111 } | 114 } |
112 */ | 115 */ |
113 | 116 |
114 static bool bridgeOp(SkTArray<SkOpContour*, true>& contourList, const SkPathOp o
p, | 117 static bool bridgeOp(SkTArray<SkOpContour*, true>& contourList, const SkPathOp o
p, |
115 const int xorMask, const int xorOpMask, SkPathWriter* simple) { | 118 const int xorMask, const int xorOpMask, SkPathWriter* simple) { |
116 bool firstContour = true; | 119 bool firstContour = true; |
117 bool unsortable = false; | 120 bool unsortable = false; |
118 bool topUnsortable = false; | 121 bool topUnsortable = false; |
| 122 bool firstPass = true; |
| 123 SkPoint lastTopLeft; |
119 SkPoint topLeft = {SK_ScalarMin, SK_ScalarMin}; | 124 SkPoint topLeft = {SK_ScalarMin, SK_ScalarMin}; |
120 do { | 125 do { |
121 int index, endIndex; | 126 int index, endIndex; |
122 bool done; | 127 bool topDone; |
| 128 lastTopLeft = topLeft; |
123 SkOpSegment* current = FindSortableTop(contourList, SkOpAngle::kBinarySi
ngle, &firstContour, | 129 SkOpSegment* current = FindSortableTop(contourList, SkOpAngle::kBinarySi
ngle, &firstContour, |
124 &index, &endIndex, &topLeft, &topUnsortable, &done); | 130 &index, &endIndex, &topLeft, &topUnsortable, &topDone, firstPass
); |
125 if (!current) { | 131 if (!current) { |
126 if (topUnsortable || !done) { | 132 if ((!topUnsortable || firstPass) && !topDone) { |
127 topUnsortable = false; | |
128 SkASSERT(topLeft.fX != SK_ScalarMin && topLeft.fY != SK_ScalarMi
n); | 133 SkASSERT(topLeft.fX != SK_ScalarMin && topLeft.fY != SK_ScalarMi
n); |
| 134 if (lastTopLeft.fX == SK_ScalarMin && lastTopLeft.fY == SK_Scala
rMin) { |
| 135 if (firstPass) { |
| 136 firstPass = false; |
| 137 } else { |
| 138 break; |
| 139 } |
| 140 } |
129 topLeft.fX = topLeft.fY = SK_ScalarMin; | 141 topLeft.fX = topLeft.fY = SK_ScalarMin; |
130 continue; | 142 continue; |
131 } | 143 } |
132 break; | 144 break; |
133 } | 145 } |
| 146 firstPass = !topUnsortable || lastTopLeft != topLeft; |
134 SkTDArray<SkOpSpan*> chaseArray; | 147 SkTDArray<SkOpSpan*> chaseArray; |
135 do { | 148 do { |
136 if (current->activeOp(index, endIndex, xorMask, xorOpMask, op)) { | 149 if (current->activeOp(index, endIndex, xorMask, xorOpMask, op)) { |
137 do { | 150 do { |
138 if (!unsortable && current->done()) { | 151 if (!unsortable && current->done()) { |
139 if (simple->isEmpty()) { | 152 if (simple->isEmpty()) { |
140 simple->init(); | 153 simple->init(); |
141 } | 154 } |
142 break; | 155 break; |
143 } | 156 } |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 { // if some edges could not be resolved, assemble remaining fragments | 300 { // if some edges could not be resolved, assemble remaining fragments |
288 SkPath temp; | 301 SkPath temp; |
289 temp.setFillType(fillType); | 302 temp.setFillType(fillType); |
290 SkPathWriter assembled(temp); | 303 SkPathWriter assembled(temp); |
291 Assemble(wrapper, &assembled); | 304 Assemble(wrapper, &assembled); |
292 *result = *assembled.nativePath(); | 305 *result = *assembled.nativePath(); |
293 result->setFillType(fillType); | 306 result->setFillType(fillType); |
294 } | 307 } |
295 return true; | 308 return true; |
296 } | 309 } |
OLD | NEW |