| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 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 | 7 |
| 8 // given a prospective edge, compute its initial winding by projecting a ray | 8 // given a prospective edge, compute its initial winding by projecting a ray |
| 9 // if the ray hits another edge | 9 // if the ray hits another edge |
| 10 // if the edge doesn't have a winding yet, hop up to that edge and start ove
r | 10 // if the edge doesn't have a winding yet, hop up to that edge and start ove
r |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 } | 75 } |
| 76 | 76 |
| 77 static bool ccw_dxdy(const SkDVector& v, SkOpRayDir dir) { | 77 static bool ccw_dxdy(const SkDVector& v, SkOpRayDir dir) { |
| 78 bool vPartPos = pt_dydx(v, dir) > 0; | 78 bool vPartPos = pt_dydx(v, dir) > 0; |
| 79 bool leftBottom = ((static_cast<int>(dir) + 1) & 2) != 0; | 79 bool leftBottom = ((static_cast<int>(dir) + 1) & 2) != 0; |
| 80 return vPartPos == leftBottom; | 80 return vPartPos == leftBottom; |
| 81 } | 81 } |
| 82 | 82 |
| 83 struct SkOpRayHit { | 83 struct SkOpRayHit { |
| 84 SkOpRayDir makeTestBase(SkOpSpan* span, double t) { | 84 SkOpRayDir makeTestBase(SkOpSpan* span, double t) { |
| 85 fNext = NULL; | 85 fNext = nullptr; |
| 86 fSpan = span; | 86 fSpan = span; |
| 87 fT = span->t() * (1 - t) + span->next()->t() * t; | 87 fT = span->t() * (1 - t) + span->next()->t() * t; |
| 88 SkOpSegment* segment = span->segment(); | 88 SkOpSegment* segment = span->segment(); |
| 89 fSlope = segment->dSlopeAtT(fT); | 89 fSlope = segment->dSlopeAtT(fT); |
| 90 fPt = segment->ptAtT(fT); | 90 fPt = segment->ptAtT(fT); |
| 91 fValid = true; | 91 fValid = true; |
| 92 return fabs(fSlope.fX) < fabs(fSlope.fY) ? SkOpRayDir::kLeft : SkOpRayDi
r::kTop; | 92 return fabs(fSlope.fX) < fabs(fSlope.fY) ? SkOpRayDir::kLeft : SkOpRayDi
r::kTop; |
| 93 } | 93 } |
| 94 | 94 |
| 95 SkOpRayHit* fNext; | 95 SkOpRayHit* fNext; |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 184 *hits = newHit; | 184 *hits = newHit; |
| 185 } | 185 } |
| 186 } | 186 } |
| 187 | 187 |
| 188 SkOpSpan* SkOpSegment::windingSpanAtT(double tHit) { | 188 SkOpSpan* SkOpSegment::windingSpanAtT(double tHit) { |
| 189 SkOpSpan* span = &fHead; | 189 SkOpSpan* span = &fHead; |
| 190 SkOpSpanBase* next; | 190 SkOpSpanBase* next; |
| 191 do { | 191 do { |
| 192 next = span->next(); | 192 next = span->next(); |
| 193 if (approximately_equal(tHit, next->t())) { | 193 if (approximately_equal(tHit, next->t())) { |
| 194 return NULL; | 194 return nullptr; |
| 195 } | 195 } |
| 196 if (tHit < next->t()) { | 196 if (tHit < next->t()) { |
| 197 return span; | 197 return span; |
| 198 } | 198 } |
| 199 } while (!next->final() && (span = next->upCast())); | 199 } while (!next->final() && (span = next->upCast())); |
| 200 return NULL; | 200 return nullptr; |
| 201 } | 201 } |
| 202 | 202 |
| 203 static bool hit_compare_x(const SkOpRayHit* a, const SkOpRayHit* b) { | 203 static bool hit_compare_x(const SkOpRayHit* a, const SkOpRayHit* b) { |
| 204 return a->fPt.fX < b->fPt.fX; | 204 return a->fPt.fX < b->fPt.fX; |
| 205 } | 205 } |
| 206 | 206 |
| 207 static bool reverse_hit_compare_x(const SkOpRayHit* a, const SkOpRayHit* b) { | 207 static bool reverse_hit_compare_x(const SkOpRayHit* a, const SkOpRayHit* b) { |
| 208 return b->fPt.fX < a->fPt.fX; | 208 return b->fPt.fX < a->fPt.fX; |
| 209 } | 209 } |
| 210 | 210 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 259 ? less_than(dir) ? hit_compare_y : reverse_hit_compare_y | 259 ? less_than(dir) ? hit_compare_y : reverse_hit_compare_y |
| 260 : less_than(dir) ? hit_compare_x : reverse_hit_compare_x); | 260 : less_than(dir) ? hit_compare_x : reverse_hit_compare_x); |
| 261 // verify windings | 261 // verify windings |
| 262 #if DEBUG_WINDING | 262 #if DEBUG_WINDING |
| 263 SkDebugf("%s dir=%s seg=%d t=%1.9g pt=(%1.9g,%1.9g)\n", __FUNCTION__, | 263 SkDebugf("%s dir=%s seg=%d t=%1.9g pt=(%1.9g,%1.9g)\n", __FUNCTION__, |
| 264 gDebugRayDirName[static_cast<int>(dir)], hitBase.fSpan->segment()->d
ebugID(), | 264 gDebugRayDirName[static_cast<int>(dir)], hitBase.fSpan->segment()->d
ebugID(), |
| 265 hitBase.fT, hitBase.fPt.fX, hitBase.fPt.fY); | 265 hitBase.fT, hitBase.fPt.fX, hitBase.fPt.fY); |
| 266 for (int index = 0; index < count; ++index) { | 266 for (int index = 0; index < count; ++index) { |
| 267 hit = sorted[index]; | 267 hit = sorted[index]; |
| 268 SkOpSpan* span = hit->fSpan; | 268 SkOpSpan* span = hit->fSpan; |
| 269 SkOpSegment* hitSegment = span ? span->segment() : NULL; | 269 SkOpSegment* hitSegment = span ? span->segment() : nullptr; |
| 270 bool operand = span ? hitSegment->operand() : false; | 270 bool operand = span ? hitSegment->operand() : false; |
| 271 bool ccw = ccw_dxdy(hit->fSlope, dir); | 271 bool ccw = ccw_dxdy(hit->fSlope, dir); |
| 272 SkDebugf("%s [%d] valid=%d operand=%d span=%d ccw=%d ", __FUNCTION__, in
dex, | 272 SkDebugf("%s [%d] valid=%d operand=%d span=%d ccw=%d ", __FUNCTION__, in
dex, |
| 273 hit->fValid, operand, span ? span->debugID() : -1, ccw); | 273 hit->fValid, operand, span ? span->debugID() : -1, ccw); |
| 274 if (span) { | 274 if (span) { |
| 275 hitSegment->dumpPtsInner(); | 275 hitSegment->dumpPtsInner(); |
| 276 } | 276 } |
| 277 SkDebugf(" t=%1.9g pt=(%1.9g,%1.9g) slope=(%1.9g,%1.9g)\n", hit->fT, | 277 SkDebugf(" t=%1.9g pt=(%1.9g,%1.9g) slope=(%1.9g,%1.9g)\n", hit->fT, |
| 278 hit->fPt.fX, hit->fPt.fY, hit->fSlope.fX, hit->fSlope.fY); | 278 hit->fPt.fX, hit->fPt.fY, hit->fSlope.fX, hit->fSlope.fY); |
| 279 } | 279 } |
| 280 #endif | 280 #endif |
| 281 const SkPoint* last = NULL; | 281 const SkPoint* last = nullptr; |
| 282 int wind = 0; | 282 int wind = 0; |
| 283 int oppWind = 0; | 283 int oppWind = 0; |
| 284 for (int index = 0; index < count; ++index) { | 284 for (int index = 0; index < count; ++index) { |
| 285 hit = sorted[index]; | 285 hit = sorted[index]; |
| 286 if (!hit->fValid) { | 286 if (!hit->fValid) { |
| 287 return false; | 287 return false; |
| 288 } | 288 } |
| 289 bool ccw = ccw_dxdy(hit->fSlope, dir); | 289 bool ccw = ccw_dxdy(hit->fSlope, dir); |
| 290 SkASSERT(!approximately_zero(hit->fT) || !hit->fValid); | 290 SkASSERT(!approximately_zero(hit->fT) || !hit->fValid); |
| 291 SkOpSpan* span = hit->fSpan; | 291 SkOpSpan* span = hit->fSpan; |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 338 #if 0 | 338 #if 0 |
| 339 SkASSERT(hitSegment->oppXor() ? (oppSum & 1) == (oSpanSum & 1) : opp
Sum == oSpanSum | 339 SkASSERT(hitSegment->oppXor() ? (oppSum & 1) == (oSpanSum & 1) : opp
Sum == oSpanSum |
| 340 || (abs(oppWind) == abs(lastOpp) | 340 || (abs(oppWind) == abs(lastOpp) |
| 341 && (oppSum ^ oppWind ^ lastOpp) == oSpanSum)); | 341 && (oppSum ^ oppWind ^ lastOpp) == oSpanSum)); |
| 342 #endif | 342 #endif |
| 343 } | 343 } |
| 344 if (sumSet) { | 344 if (sumSet) { |
| 345 if (this->globalState()->phase() == SkOpGlobalState::kFixWinding) { | 345 if (this->globalState()->phase() == SkOpGlobalState::kFixWinding) { |
| 346 hitSegment->contour()->setCcw(ccw); | 346 hitSegment->contour()->setCcw(ccw); |
| 347 } else { | 347 } else { |
| 348 (void) hitSegment->markAndChaseWinding(span, span->next(), windS
um, oppSum, NULL); | 348 (void) hitSegment->markAndChaseWinding(span, span->next(), windS
um, oppSum, nullptr); |
| 349 (void) hitSegment->markAndChaseWinding(span->next(), span, windS
um, oppSum, NULL); | 349 (void) hitSegment->markAndChaseWinding(span->next(), span, windS
um, oppSum, nullptr); |
| 350 } | 350 } |
| 351 } | 351 } |
| 352 if (operand) { | 352 if (operand) { |
| 353 SkTSwap(wind, oppWind); | 353 SkTSwap(wind, oppWind); |
| 354 } | 354 } |
| 355 last = &hit->fPt; | 355 last = &hit->fPt; |
| 356 this->globalState()->bumpNested(); | 356 this->globalState()->bumpNested(); |
| 357 } | 357 } |
| 358 return true; | 358 return true; |
| 359 } | 359 } |
| 360 | 360 |
| 361 SkOpSpan* SkOpSegment::findSortableTop(SkOpContour* contourHead) { | 361 SkOpSpan* SkOpSegment::findSortableTop(SkOpContour* contourHead) { |
| 362 SkOpSpan* span = &fHead; | 362 SkOpSpan* span = &fHead; |
| 363 SkOpSpanBase* next; | 363 SkOpSpanBase* next; |
| 364 do { | 364 do { |
| 365 next = span->next(); | 365 next = span->next(); |
| 366 if (span->done()) { | 366 if (span->done()) { |
| 367 continue; | 367 continue; |
| 368 } | 368 } |
| 369 if (span->windSum() != SK_MinS32) { | 369 if (span->windSum() != SK_MinS32) { |
| 370 return span; | 370 return span; |
| 371 } | 371 } |
| 372 if (span->sortableTop(contourHead)) { | 372 if (span->sortableTop(contourHead)) { |
| 373 return span; | 373 return span; |
| 374 } | 374 } |
| 375 } while (!next->final() && (span = next->upCast())); | 375 } while (!next->final() && (span = next->upCast())); |
| 376 return NULL; | 376 return nullptr; |
| 377 } | 377 } |
| 378 | 378 |
| 379 SkOpSpan* SkOpContour::findSortableTop(SkOpContour* contourHead) { | 379 SkOpSpan* SkOpContour::findSortableTop(SkOpContour* contourHead) { |
| 380 SkOpSegment* testSegment = &fHead; | 380 SkOpSegment* testSegment = &fHead; |
| 381 do { | 381 do { |
| 382 if (testSegment->done()) { | 382 if (testSegment->done()) { |
| 383 continue; | 383 continue; |
| 384 } | 384 } |
| 385 SkOpSpan* result = testSegment->findSortableTop(contourHead); | 385 SkOpSpan* result = testSegment->findSortableTop(contourHead); |
| 386 if (result) { | 386 if (result) { |
| 387 return result; | 387 return result; |
| 388 } | 388 } |
| 389 } while ((testSegment = testSegment->next())); | 389 } while ((testSegment = testSegment->next())); |
| 390 return NULL; | 390 return nullptr; |
| 391 } | 391 } |
| 392 | 392 |
| 393 SkOpSpan* FindSortableTop(SkOpContourHead* contourHead) { | 393 SkOpSpan* FindSortableTop(SkOpContourHead* contourHead) { |
| 394 for (int index = 0; index < SkOpGlobalState::kMaxWindingTries; ++index) { | 394 for (int index = 0; index < SkOpGlobalState::kMaxWindingTries; ++index) { |
| 395 SkOpContour* contour = contourHead; | 395 SkOpContour* contour = contourHead; |
| 396 do { | 396 do { |
| 397 if (contour->done()) { | 397 if (contour->done()) { |
| 398 continue; | 398 continue; |
| 399 } | 399 } |
| 400 SkOpSpan* result = contour->findSortableTop(contourHead); | 400 SkOpSpan* result = contour->findSortableTop(contourHead); |
| 401 if (result) { | 401 if (result) { |
| 402 return result; | 402 return result; |
| 403 } | 403 } |
| 404 } while ((contour = contour->next())); | 404 } while ((contour = contour->next())); |
| 405 } | 405 } |
| 406 return NULL; | 406 return nullptr; |
| 407 } | 407 } |
| OLD | NEW |