Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(63)

Side by Side Diff: src/pathops/SkOpAngle.cpp

Issue 14865019: path ops work in progress (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/pathops/SkOpAngle.h ('k') | src/pathops/SkOpSegment.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "SkIntersections.h" 7 #include "SkIntersections.h"
8 #include "SkOpAngle.h" 8 #include "SkOpAngle.h"
9 #include "SkOpSegment.h"
9 #include "SkPathOpsCurve.h" 10 #include "SkPathOpsCurve.h"
10 #include "SkTSort.h" 11 #include "SkTSort.h"
11 12
12 #if DEBUG_SORT || DEBUG_SORT_SINGLE
13 #include "SkOpSegment.h"
14 #endif
15 13
16 // FIXME: this is bogus for quads and cubics 14 // FIXME: this is bogus for quads and cubics
17 // if the quads and cubics' line from end pt to ctrl pt are coincident, 15 // if the quads and cubics' line from end pt to ctrl pt are coincident,
18 // there's no obvious way to determine the curve ordering from the 16 // there's no obvious way to determine the curve ordering from the
19 // derivatives alone. In particular, if one quadratic's coincident tangent 17 // derivatives alone. In particular, if one quadratic's coincident tangent
20 // is longer than the other curve, the final control point can place the 18 // is longer than the other curve, the final control point can place the
21 // longer curve on either side of the shorter one. 19 // longer curve on either side of the shorter one.
22 // Using Bezier curve focus http://cagd.cs.byu.edu/~tom/papers/bezclip.pdf 20 // Using Bezier curve focus http://cagd.cs.byu.edu/~tom/papers/bezclip.pdf
23 // may provide some help, but nothing has been figured out yet. 21 // may provide some help, but nothing has been figured out yet.
24 22
25 /*( 23 /*(
26 for quads and cubics, set up a parameterized line (e.g. LineParameters ) 24 for quads and cubics, set up a parameterized line (e.g. LineParameters )
27 for points [0] to [1]. See if point [2] is on that line, or on one side 25 for points [0] to [1]. See if point [2] is on that line, or on one side
28 or the other. If it both quads' end points are on the same side, choose 26 or the other. If it both quads' end points are on the same side, choose
29 the shorter tangent. If the tangents are equal, choose the better second 27 the shorter tangent. If the tangents are equal, choose the better second
30 tangent angle 28 tangent angle
31 29
32 maybe I could set up LineParameters lazily 30 maybe I could set up LineParameters lazily
33 */ 31 */
34 static int simple_compare(double x, double y, double rx, double ry) { 32 static int simple_compare(double x, double y, double rx, double ry, double error ) {
33 SkASSERT(error);
35 if ((y < 0) ^ (ry < 0)) { // OPTIMIZATION: better to use y * ry < 0 ? 34 if ((y < 0) ^ (ry < 0)) { // OPTIMIZATION: better to use y * ry < 0 ?
36 return y < 0; 35 return y < 0;
37 } 36 }
38 if (y == 0 && ry == 0 && x * rx < 0) { 37 if (y == 0 && ry == 0 && x * rx < 0) {
39 return x < rx; 38 return x < rx;
40 } 39 }
41 double x_ry = x * ry; 40 double x_ry = x * ry;
42 double rx_y = rx * y; 41 double rx_y = rx * y;
43 double cmp = x_ry - rx_y; 42 double cmp = (x_ry - rx_y) * error;
44 if (!approximately_zero(cmp)) { 43 if (!approximately_zero(cmp)) {
45 return cmp < 0; 44 return cmp < 0;
46 } 45 }
47 if (approximately_zero(x_ry) && approximately_zero(rx_y) 46 if (approximately_zero(x_ry) && approximately_zero(rx_y)
48 && !approximately_zero_squared(cmp)) { 47 && !approximately_zero_squared(cmp)) {
49 return cmp < 0; 48 return cmp < 0;
50 } 49 }
51 return -1; 50 return -1;
52 } 51 }
53 52
53 static double gError[] = {
54 0, 1, 1.0/2, 1.0/3
55 };
56
54 bool SkOpAngle::operator<(const SkOpAngle& rh) const { 57 bool SkOpAngle::operator<(const SkOpAngle& rh) const {
55 double x = dx(); 58 double x = dx();
56 double y = dy(); 59 double y = dy();
57 double rx = rh.dx(); 60 double rx = rh.dx();
58 double ry = rh.dy(); 61 double ry = rh.dy();
59 int simple = simple_compare(x, y, rx, ry); 62 SkPath::Verb verb = fSegment->verb();
63 SkPath::Verb rVerb = rh.fSegment->verb();
64 int simple = simple_compare(x, y, rx, ry, gError[verb] * gError[rVerb]);
60 if (simple >= 0) { 65 if (simple >= 0) {
61 return simple; 66 return simple;
62 } 67 }
63 // at this point, the initial tangent line is coincident 68 // at this point, the initial tangent line is coincident
64 // see if edges curl away from each other 69 // see if edges curl away from each other
65 if (fSide * rh.fSide <= 0 && (!approximately_zero(fSide) 70 if (fSide * rh.fSide <= 0 && (!approximately_zero(fSide)
66 || !approximately_zero(rh.fSide))) { 71 || !approximately_zero(rh.fSide))) {
67 // FIXME: running demo will trigger this assertion 72 // FIXME: running demo will trigger this assertion
68 // (don't know if commenting out will trigger further assertion or not) 73 // (don't know if commenting out will trigger further assertion or not)
69 // commenting it out allows demo to run in release, though 74 // commenting it out allows demo to run in release, though
70 return fSide < rh.fSide; 75 return fSide < rh.fSide;
71 } 76 }
72 // see if either curve can be lengthened and try the tangent compare again 77 // see if either curve can be lengthened and try the tangent compare again
73 if (/* cmp && */ (*fSpans)[fEnd].fOther != rh.fSegment // tangents not abso lutely identical 78 if (fSegment->other(fEnd) != rh.fSegment // tangents not absolutely identic al
74 && (*rh.fSpans)[rh.fEnd].fOther != fSegment) { // and not intersect ing 79 && rh.fSegment->other(rh.fEnd) != fSegment) { // and not intersecti ng
75 SkOpAngle longer = *this; 80 SkOpAngle longer = *this;
76 SkOpAngle rhLonger = rh; 81 SkOpAngle rhLonger = rh;
77 if (longer.lengthen() | rhLonger.lengthen()) { 82 if (longer.lengthen() | rhLonger.lengthen()) {
78 return longer < rhLonger; 83 return longer < rhLonger;
79 } 84 }
80 } 85 }
81 if ((fVerb == SkPath::kLine_Verb && approximately_zero(x) && approximately_z ero(y)) 86 if ((verb == SkPath::kLine_Verb && approximately_zero(x) && approximately_ze ro(y))
82 || (rh.fVerb == SkPath::kLine_Verb 87 || (rVerb == SkPath::kLine_Verb
83 && approximately_zero(rx) && approximately_zero(ry))) { 88 && approximately_zero(rx) && approximately_zero(ry))) {
84 // See general unsortable comment below. This case can happen when 89 // See general unsortable comment below. This case can happen when
85 // one line has a non-zero change in t but no change in x and y. 90 // one line has a non-zero change in t but no change in x and y.
86 fUnsortable = true; 91 fUnsortable = true;
87 rh.fUnsortable = true; 92 rh.fUnsortable = true;
88 return this < &rh; // even with no solution, return a stable sort 93 return this < &rh; // even with no solution, return a stable sort
89 } 94 }
90 if ((*rh.fSpans)[SkMin32(rh.fStart, rh.fEnd)].fTiny 95 if (fSegment->isTiny(this) || rh.fSegment->isTiny(&rh)) {
91 || (*fSpans)[SkMin32(fStart, fEnd)].fTiny) {
92 fUnsortable = true; 96 fUnsortable = true;
93 rh.fUnsortable = true; 97 rh.fUnsortable = true;
94 return this < &rh; // even with no solution, return a stable sort 98 return this < &rh; // even with no solution, return a stable sort
95 } 99 }
96 SkASSERT(fVerb >= SkPath::kQuad_Verb); 100 SkASSERT(verb >= SkPath::kQuad_Verb);
97 SkASSERT(rh.fVerb >= SkPath::kQuad_Verb); 101 SkASSERT(rVerb >= SkPath::kQuad_Verb);
98 // FIXME: until I can think of something better, project a ray from the 102 // FIXME: until I can think of something better, project a ray from the
99 // end of the shorter tangent to midway between the end points 103 // end of the shorter tangent to midway between the end points
100 // through both curves and use the resulting angle to sort 104 // through both curves and use the resulting angle to sort
101 // FIXME: some of this setup can be moved to set() if it works, or cached if it's expensive 105 // FIXME: some of this setup can be moved to set() if it works, or cached if it's expensive
102 double len = fTangent1.normalSquared(); 106 double len = fTangent1.normalSquared();
103 double rlen = rh.fTangent1.normalSquared(); 107 double rlen = rh.fTangent1.normalSquared();
104 SkDLine ray; 108 SkDLine ray;
105 SkIntersections i, ri; 109 SkIntersections i, ri;
106 int roots, rroots; 110 int roots, rroots;
107 bool flip = false; 111 bool flip = false;
108 bool useThis; 112 bool useThis;
109 bool leftLessThanRight = fSide > 0; 113 bool leftLessThanRight = fSide > 0;
110 do { 114 do {
111 useThis = (len < rlen) ^ flip; 115 useThis = (len < rlen) ^ flip;
112 const SkDCubic& part = useThis ? fCurvePart : rh.fCurvePart; 116 const SkDCubic& part = useThis ? fCurvePart : rh.fCurvePart;
113 SkPath::Verb partVerb = useThis ? fVerb : rh.fVerb; 117 SkPath::Verb partVerb = useThis ? verb : rVerb;
114 ray[0] = partVerb == SkPath::kCubic_Verb && part[0].approximatelyEqual(p art[1]) ? 118 ray[0] = partVerb == SkPath::kCubic_Verb && part[0].approximatelyEqual(p art[1]) ?
115 part[2] : part[1]; 119 part[2] : part[1];
116 ray[1].fX = (part[0].fX + part[partVerb].fX) / 2; 120 ray[1].fX = (part[0].fX + part[partVerb].fX) / 2;
117 ray[1].fY = (part[0].fY + part[partVerb].fY) / 2; 121 ray[1].fY = (part[0].fY + part[partVerb].fY) / 2;
118 SkASSERT(ray[0] != ray[1]); 122 SkASSERT(ray[0] != ray[1]);
119 roots = (i.*CurveRay[fVerb])(fPts, ray); 123 roots = (i.*CurveRay[verb])(fSegment->pts(), ray);
120 rroots = (ri.*CurveRay[rh.fVerb])(rh.fPts, ray); 124 rroots = (ri.*CurveRay[rVerb])(rh.fSegment->pts(), ray);
121 } while ((roots == 0 || rroots == 0) && (flip ^= true)); 125 } while ((roots == 0 || rroots == 0) && (flip ^= true));
122 if (roots == 0 || rroots == 0) { 126 if (roots == 0 || rroots == 0) {
123 // FIXME: we don't have a solution in this case. The interim solution 127 // FIXME: we don't have a solution in this case. The interim solution
124 // is to mark the edges as unsortable, exclude them from this and 128 // is to mark the edges as unsortable, exclude them from this and
125 // future computations, and allow the returned path to be fragmented 129 // future computations, and allow the returned path to be fragmented
126 fUnsortable = true; 130 fUnsortable = true;
127 rh.fUnsortable = true; 131 rh.fUnsortable = true;
128 return this < &rh; // even with no solution, return a stable sort 132 return this < &rh; // even with no solution, return a stable sort
129 } 133 }
130 SkASSERT(fSide != 0 && rh.fSide != 0); 134 SkASSERT(fSide != 0 && rh.fSide != 0);
(...skipping 29 matching lines...) Expand all
160 best, dist, "><"[fSide < 0], rLoc.fX, rLoc.fY, dxy.fX, dxy.fY); 164 best, dist, "><"[fSide < 0], rLoc.fX, rLoc.fY, dxy.fX, dxy.fY);
161 #endif 165 #endif
162 if (best > dist) { 166 if (best > dist) {
163 flip = true; 167 flip = true;
164 break; 168 break;
165 } 169 }
166 } 170 }
167 #if 0 171 #if 0
168 SkDVector lRay = lLoc - fCurvePart[0]; 172 SkDVector lRay = lLoc - fCurvePart[0];
169 SkDVector rRay = rLoc - fCurvePart[0]; 173 SkDVector rRay = rLoc - fCurvePart[0];
170 int rayDir = simple_compare(lRay.fX, lRay.fY, rRay.fX, rRay.fY); 174 int rayDir = simple_compare(lRay.fX, lRay.fY, rRay.fX, rRay.fY, gError[verb] * gError[rVerb]);
171 SkASSERT(rayDir >= 0); 175 SkASSERT(rayDir >= 0);
172 if (rayDir < 0) { 176 if (rayDir < 0) {
173 fUnsortable = true; 177 fUnsortable = true;
174 rh.fUnsortable = true; 178 rh.fUnsortable = true;
175 return this < &rh; // even with no solution, return a stable sort 179 return this < &rh; // even with no solution, return a stable sort
176 } 180 }
177 #endif 181 #endif
178 if (flip) { 182 if (flip) {
179 leftLessThanRight = !leftLessThanRight; 183 leftLessThanRight = !leftLessThanRight;
180 // rayDir = !rayDir; 184 // rayDir = !rayDir;
181 } 185 }
182 #if 0 && (DEBUG_SORT || DEBUG_SORT_SINGLE) 186 #if 0 && (DEBUG_SORT || DEBUG_SORT_SINGLE)
183 SkDebugf("%d %c %d (fSide %c 0) loc={{%1.9g,%1.9g}, {%1.9g,%1.9g}} flip=%d r ayDir=%d\n", 187 SkDebugf("%d %c %d (fSide %c 0) loc={{%1.9g,%1.9g}, {%1.9g,%1.9g}} flip=%d r ayDir=%d\n",
184 fSegment->debugID(), "><"[leftLessThanRight], rh.fSegment->debug ID(), 188 fSegment->debugID(), "><"[leftLessThanRight], rh.fSegment->debug ID(),
185 "<>"[fSide > 0], lLoc.fX, lLoc.fY, rLoc.fX, rLoc.fY, flip, rayDi r); 189 "<>"[fSide > 0], lLoc.fX, lLoc.fY, rLoc.fX, rLoc.fY, flip, rayDi r);
186 #endif 190 #endif
187 // SkASSERT(leftLessThanRight == (bool) rayDir); 191 // SkASSERT(leftLessThanRight == (bool) rayDir);
188 return leftLessThanRight; 192 return leftLessThanRight;
189 } 193 }
190 194
195 bool SkOpAngle::isHorizontal() const {
196 return dy() == 0 && fSegment->verb() == SkPath::kLine_Verb;
197 }
198
191 bool SkOpAngle::lengthen() { 199 bool SkOpAngle::lengthen() {
192 int newEnd = fEnd; 200 int newEnd = fEnd;
193 if (fStart < fEnd ? ++newEnd < fSpans->count() : --newEnd >= 0) { 201 if (fStart < fEnd ? ++newEnd < fSegment->count() : --newEnd >= 0) {
194 fEnd = newEnd; 202 fEnd = newEnd;
195 setSpans(); 203 setSpans();
196 return true; 204 return true;
197 } 205 }
198 return false; 206 return false;
199 } 207 }
200 208
201 bool SkOpAngle::reverseLengthen() { 209 bool SkOpAngle::reverseLengthen() {
202 if (fReversed) { 210 if (fReversed) {
203 return false; 211 return false;
204 } 212 }
205 int newEnd = fStart; 213 int newEnd = fStart;
206 if (fStart > fEnd ? ++newEnd < fSpans->count() : --newEnd >= 0) { 214 if (fStart > fEnd ? ++newEnd < fSegment->count() : --newEnd >= 0) {
207 fEnd = newEnd; 215 fEnd = newEnd;
208 fReversed = true; 216 fReversed = true;
209 setSpans(); 217 setSpans();
210 return true; 218 return true;
211 } 219 }
212 return false; 220 return false;
213 } 221 }
214 222
215 void SkOpAngle::set(const SkPoint* orig, SkPath::Verb verb, const SkOpSegment* s egment, 223 void SkOpAngle::set(const SkPoint* orig, SkPath::Verb verb, const SkOpSegment* s egment,
216 int start, int end, const SkTDArray<SkOpSpan>& spans) { 224 int start, int end, const SkTDArray<SkOpSpan>& spans) {
217 fSegment = segment; 225 fSegment = segment;
218 fStart = start; 226 fStart = start;
219 fEnd = end; 227 fEnd = end;
220 fPts = orig; 228 if (fSegment->isTiny(this) && (start == 0 || end == fSegment->count() - 1)) {
221 fVerb = verb; 229 fUnsortable = true;
222 fSpans = &spans; 230 return;
231 }
223 fReversed = false; 232 fReversed = false;
224 fUnsortable = false; 233 fUnsortable = false;
225 setSpans(); 234 setSpans();
226 } 235 }
227 236
228 237
229 void SkOpAngle::setSpans() { 238 void SkOpAngle::setSpans() {
230 double startT = (*fSpans)[fStart].fT; 239 fSegment->subDivide(fStart, fEnd, &fCurvePart);
231 double endT = (*fSpans)[fEnd].fT; 240 switch (fSegment->verb()) {
232 switch (fVerb) {
233 case SkPath::kLine_Verb: { 241 case SkPath::kLine_Verb: {
234 SkDLine l = SkDLine::SubDivide(fPts, startT, endT);
235 // OPTIMIZATION: for pure line compares, we never need fTangent1.c 242 // OPTIMIZATION: for pure line compares, we never need fTangent1.c
236 fTangent1.lineEndPoints(l); 243 fTangent1.lineEndPoints(*SkTCast<SkDLine*>(&fCurvePart));
237 fSide = 0; 244 fSide = 0;
238 } break; 245 } break;
239 case SkPath::kQuad_Verb: { 246 case SkPath::kQuad_Verb: {
240 SkDQuad& quad = *SkTCast<SkDQuad*>(&fCurvePart); 247 SkDQuad& quad = *SkTCast<SkDQuad*>(&fCurvePart);
241 quad = SkDQuad::SubDivide(fPts, startT, endT);
242 fTangent1.quadEndPoints(quad, 0, 1); 248 fTangent1.quadEndPoints(quad, 0, 1);
243 if (dx() == 0 && dy() == 0) { 249 if (dx() == 0 && dy() == 0) {
244 fTangent1.quadEndPoints(quad); 250 fTangent1.quadEndPoints(quad);
245 } 251 }
246 fSide = -fTangent1.pointDistance(fCurvePart[2]); // not normalized -- c ompare sign only 252 fSide = -fTangent1.pointDistance(fCurvePart[2]); // not normalized -- c ompare sign only
247 } break; 253 } break;
248 case SkPath::kCubic_Verb: { 254 case SkPath::kCubic_Verb: {
249 // int nextC = 2; 255 // int nextC = 2;
250 fCurvePart = SkDCubic::SubDivide(fPts, startT, endT);
251 fTangent1.cubicEndPoints(fCurvePart, 0, 1); 256 fTangent1.cubicEndPoints(fCurvePart, 0, 1);
252 if (dx() == 0 && dy() == 0) { 257 if (dx() == 0 && dy() == 0) {
253 fTangent1.cubicEndPoints(fCurvePart, 0, 2); 258 fTangent1.cubicEndPoints(fCurvePart, 0, 2);
254 // nextC = 3; 259 // nextC = 3;
255 if (dx() == 0 && dy() == 0) { 260 if (dx() == 0 && dy() == 0) {
256 fTangent1.cubicEndPoints(fCurvePart, 0, 3); 261 fTangent1.cubicEndPoints(fCurvePart, 0, 3);
257 } 262 }
258 } 263 }
259 // fSide = -fTangent1.pointDistance(fCurvePart[nextC]); // compare sign on ly 264 // fSide = -fTangent1.pointDistance(fCurvePart[nextC]); // compare sign on ly
260 // if (nextC == 2 && approximately_zero(fSide)) { 265 // if (nextC == 2 && approximately_zero(fSide)) {
261 // fSide = -fTangent1.pointDistance(fCurvePart[3]); 266 // fSide = -fTangent1.pointDistance(fCurvePart[3]);
262 // } 267 // }
263 double testTs[4]; 268 double testTs[4];
264 // OPTIMIZATION: keep inflections precomputed with cubic segment? 269 // OPTIMIZATION: keep inflections precomputed with cubic segment?
265 int testCount = SkDCubic::FindInflections(fPts, testTs); 270 const SkPoint* pts = fSegment->pts();
271 int testCount = SkDCubic::FindInflections(pts, testTs);
272 double startT = fSegment->t(fStart);
273 double endT = fSegment->t(fEnd);
266 double limitT = endT; 274 double limitT = endT;
267 int index; 275 int index;
268 for (index = 0; index < testCount; ++index) { 276 for (index = 0; index < testCount; ++index) {
269 if (!between(startT, testTs[index], limitT)) { 277 if (!between(startT, testTs[index], limitT)) {
270 testTs[index] = -1; 278 testTs[index] = -1;
271 } 279 }
272 } 280 }
273 testTs[testCount++] = startT; 281 testTs[testCount++] = startT;
274 testTs[testCount++] = endT; 282 testTs[testCount++] = endT;
275 SkTQSort<double>(testTs, &testTs[testCount - 1]); 283 SkTQSort<double>(testTs, &testTs[testCount - 1]);
276 double bestSide = 0; 284 double bestSide = 0;
277 int testCases = (testCount << 1) - 1; 285 int testCases = (testCount << 1) - 1;
278 index = 0; 286 index = 0;
279 while (testTs[index] < 0) { 287 while (testTs[index] < 0) {
280 ++index; 288 ++index;
281 } 289 }
282 index <<= 1; 290 index <<= 1;
283 for (; index < testCases; ++index) { 291 for (; index < testCases; ++index) {
284 int testIndex = index >> 1; 292 int testIndex = index >> 1;
285 double testT = testTs[testIndex]; 293 double testT = testTs[testIndex];
286 if (index & 1) { 294 if (index & 1) {
287 testT = (testT + testTs[testIndex + 1]) / 2; 295 testT = (testT + testTs[testIndex + 1]) / 2;
288 } 296 }
289 // OPTIMIZE: could avoid call for t == startT, endT 297 // OPTIMIZE: could avoid call for t == startT, endT
290 SkDPoint pt = dcubic_xy_at_t(fPts, testT); 298 SkDPoint pt = dcubic_xy_at_t(pts, testT);
291 double testSide = fTangent1.pointDistance(pt); 299 double testSide = fTangent1.pointDistance(pt);
292 if (fabs(bestSide) < fabs(testSide)) { 300 if (fabs(bestSide) < fabs(testSide)) {
293 bestSide = testSide; 301 bestSide = testSide;
294 } 302 }
295 } 303 }
296 fSide = -bestSide; // compare sign only 304 fSide = -bestSide; // compare sign only
297 } break; 305 } break;
298 default: 306 default:
299 SkASSERT(0); 307 SkASSERT(0);
300 } 308 }
301 fUnsortable = dx() == 0 && dy() == 0; 309 fUnsortable = dx() == 0 && dy() == 0;
302 if (fUnsortable) { 310 if (fUnsortable) {
303 return; 311 return;
304 } 312 }
305 SkASSERT(fStart != fEnd); 313 SkASSERT(fStart != fEnd);
306 int step = fStart < fEnd ? 1 : -1; // OPTIMIZE: worth fStart - fEnd >> 31 t ype macro? 314 int step = fStart < fEnd ? 1 : -1; // OPTIMIZE: worth fStart - fEnd >> 31 t ype macro?
307 for (int index = fStart; index != fEnd; index += step) { 315 for (int index = fStart; index != fEnd; index += step) {
308 #if 1 316 #if 1
309 const SkOpSpan& thisSpan = (*fSpans)[index]; 317 const SkOpSpan& thisSpan = fSegment->span(index);
310 const SkOpSpan& nextSpan = (*fSpans)[index + step]; 318 const SkOpSpan& nextSpan = fSegment->span(index + step);
311 if (thisSpan.fTiny || precisely_equal(thisSpan.fT, nextSpan.fT)) { 319 if (thisSpan.fTiny || precisely_equal(thisSpan.fT, nextSpan.fT)) {
312 continue; 320 continue;
313 } 321 }
314 fUnsortable = step > 0 ? thisSpan.fUnsortableStart : nextSpan.fUnsortabl eEnd; 322 fUnsortable = step > 0 ? thisSpan.fUnsortableStart : nextSpan.fUnsortabl eEnd;
315 #if DEBUG_UNSORTABLE 323 #if DEBUG_UNSORTABLE
316 if (fUnsortable) { 324 if (fUnsortable) {
317 SkPoint iPt = (*CurvePointAtT[fVerb])(fPts, thisSpan.fT); 325 SkPoint iPt = fSegment->xyAtT(index);
318 SkPoint ePt = (*CurvePointAtT[fVerb])(fPts, nextSpan.fT); 326 SkPoint ePt = fSegment->xyAtT(index + step);
319 SkDebugf("%s unsortable [%d] (%1.9g,%1.9g) [%d] (%1.9g,%1.9g)\n", __ FUNCTION__, 327 SkDebugf("%s unsortable [%d] (%1.9g,%1.9g) [%d] (%1.9g,%1.9g)\n", __ FUNCTION__,
320 index, iPt.fX, iPt.fY, fEnd, ePt.fX, ePt.fY); 328 index, iPt.fX, iPt.fY, fEnd, ePt.fX, ePt.fY);
321 } 329 }
322 #endif 330 #endif
323 return; 331 return;
324 #else 332 #else
325 if ((*fSpans)[index].fUnsortableStart) { 333 if ((*fSpans)[index].fUnsortableStart) {
326 fUnsortable = true; 334 fUnsortable = true;
327 return; 335 return;
328 } 336 }
329 #endif 337 #endif
330 } 338 }
331 #if 1 339 #if 1
332 #if DEBUG_UNSORTABLE 340 #if DEBUG_UNSORTABLE
333 SkPoint iPt = (*CurvePointAtT[fVerb])(fPts, startT); 341 SkPoint iPt = fSegment->xyAtT(fStart);
334 SkPoint ePt = (*CurvePointAtT[fVerb])(fPts, endT); 342 SkPoint ePt = fSegment->xyAtT(fEnd);
335 SkDebugf("%s all tiny unsortable [%d] (%1.9g,%1.9g) [%d] (%1.9g,%1.9g)\n", _ _FUNCTION__, 343 SkDebugf("%s all tiny unsortable [%d] (%1.9g,%1.9g) [%d] (%1.9g,%1.9g)\n", _ _FUNCTION__,
336 fStart, iPt.fX, iPt.fY, fEnd, ePt.fX, ePt.fY); 344 fStart, iPt.fX, iPt.fY, fEnd, ePt.fX, ePt.fY);
337 #endif 345 #endif
338 fUnsortable = true; 346 fUnsortable = true;
339 #endif 347 #endif
340 } 348 }
OLDNEW
« no previous file with comments | « src/pathops/SkOpAngle.h ('k') | src/pathops/SkOpSegment.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698