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

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

Issue 340103002: fix last skp bug (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years, 6 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
« no previous file with comments | « src/pathops/SkOpSegment.h ('k') | src/pathops/SkPathOpsDebug.cpp » ('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 "SkOpContour.h" 8 #include "SkOpContour.h"
9 #include "SkOpSegment.h" 9 #include "SkOpSegment.h"
10 #include "SkPathWriter.h" 10 #include "SkPathWriter.h"
(...skipping 3072 matching lines...) Expand 10 before | Expand all | Expand 10 after
3083 SkASSERT(end != -1); 3083 SkASSERT(end != -1);
3084 } 3084 }
3085 // if the topmost T is not on end, or is three-way or more, find left 3085 // if the topmost T is not on end, or is three-way or more, find left
3086 // look for left-ness from tLeft to firstT (matching y of other) 3086 // look for left-ness from tLeft to firstT (matching y of other)
3087 SkASSERT(firstT - end != 0); 3087 SkASSERT(firstT - end != 0);
3088 SkOpAngle* markAngle = spanToAngle(firstT, end); 3088 SkOpAngle* markAngle = spanToAngle(firstT, end);
3089 if (!markAngle) { 3089 if (!markAngle) {
3090 markAngle = addSingletonAngles(step); 3090 markAngle = addSingletonAngles(step);
3091 } 3091 }
3092 markAngle->markStops(); 3092 markAngle->markStops();
3093 const SkOpAngle* baseAngle = markAngle->findFirst(); 3093 const SkOpAngle* baseAngle = markAngle->next() == markAngle && !isVertical() ? markAngle
3094 : markAngle->findFirst();
3094 if (!baseAngle) { 3095 if (!baseAngle) {
3095 return NULL; // nothing to do 3096 return NULL; // nothing to do
3096 } 3097 }
3097 SkScalar top = SK_ScalarMax; 3098 SkScalar top = SK_ScalarMax;
3098 const SkOpAngle* firstAngle = NULL; 3099 const SkOpAngle* firstAngle = NULL;
3099 const SkOpAngle* angle = baseAngle; 3100 const SkOpAngle* angle = baseAngle;
3100 do { 3101 do {
3101 if (!angle->unorderable()) { 3102 if (!angle->unorderable()) {
3102 SkOpSegment* next = angle->segment(); 3103 SkOpSegment* next = angle->segment();
3103 SkPathOpsBounds bounds; 3104 SkPathOpsBounds bounds;
(...skipping 26 matching lines...) Expand all
3130 } 3131 }
3131 angle = angle->next(); 3132 angle = angle->next();
3132 looped = true; 3133 looped = true;
3133 } while (angle != firstAngle); 3134 } while (angle != firstAngle);
3134 if (angle == firstAngle && looped) { 3135 if (angle == firstAngle && looped) {
3135 return NULL; 3136 return NULL;
3136 } 3137 }
3137 if (leftSegment->verb() >= SkPath::kQuad_Verb) { 3138 if (leftSegment->verb() >= SkPath::kQuad_Verb) {
3138 const int tIndex = *tIndexPtr; 3139 const int tIndex = *tIndexPtr;
3139 const int endIndex = *endIndexPtr; 3140 const int endIndex = *endIndexPtr;
3140 if (!leftSegment->clockwise(tIndex, endIndex)) { 3141 bool swap;
3141 bool swap = !leftSegment->monotonicInY(tIndex, endIndex) 3142 if (!leftSegment->clockwise(tIndex, endIndex, &swap)) {
3142 && !leftSegment->serpentine(tIndex, endIndex);
3143 #if DEBUG_SWAP_TOP 3143 #if DEBUG_SWAP_TOP
3144 SkDebugf("%s swap=%d inflections=%d serpentine=%d controlledbyends=% d monotonic=%d\n", 3144 SkDebugf("%s swap=%d inflections=%d serpentine=%d controlledbyends=% d monotonic=%d\n",
3145 __FUNCTION__, 3145 __FUNCTION__,
3146 swap, leftSegment->debugInflections(tIndex, endIndex), 3146 swap, leftSegment->debugInflections(tIndex, endIndex),
3147 leftSegment->serpentine(tIndex, endIndex), 3147 leftSegment->serpentine(tIndex, endIndex),
3148 leftSegment->controlsContainedByEnds(tIndex, endIndex), 3148 leftSegment->controlsContainedByEnds(tIndex, endIndex),
3149 leftSegment->monotonicInY(tIndex, endIndex)); 3149 leftSegment->monotonicInY(tIndex, endIndex));
3150 #endif 3150 #endif
3151 if (swap) { 3151 if (swap) {
3152 // FIXME: I doubt it makes sense to (necessarily) swap if the edge was not t he first 3152 // FIXME: I doubt it makes sense to (necessarily) swap if the edge was not t he first
(...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after
3614 SkASSERT(span.fOppSum == SK_MinS32 || span.fOppSum == oppWinding); 3614 SkASSERT(span.fOppSum == SK_MinS32 || span.fOppSum == oppWinding);
3615 #if DEBUG_LIMIT_WIND_SUM 3615 #if DEBUG_LIMIT_WIND_SUM
3616 SkASSERT(abs(oppWinding) <= DEBUG_LIMIT_WIND_SUM); 3616 SkASSERT(abs(oppWinding) <= DEBUG_LIMIT_WIND_SUM);
3617 #endif 3617 #endif
3618 span.fOppSum = oppWinding; 3618 span.fOppSum = oppWinding;
3619 debugValidate(); 3619 debugValidate();
3620 return &span; 3620 return &span;
3621 } 3621 }
3622 3622
3623 // from http://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of -polygon-points-are-in-clockwise-order 3623 // from http://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of -polygon-points-are-in-clockwise-order
3624 bool SkOpSegment::clockwise(int tStart, int tEnd) const { 3624 bool SkOpSegment::clockwise(int tStart, int tEnd, bool* swap) const {
3625 SkASSERT(fVerb != SkPath::kLine_Verb); 3625 SkASSERT(fVerb != SkPath::kLine_Verb);
3626 SkPoint edge[4]; 3626 SkPoint edge[4];
3627 subDivide(tStart, tEnd, edge); 3627 subDivide(tStart, tEnd, edge);
3628 int points = SkPathOpsVerbToPoints(fVerb); 3628 int points = SkPathOpsVerbToPoints(fVerb);
3629 double sum = (edge[0].fX - edge[points].fX) * (edge[0].fY + edge[points].fY) ; 3629 double sum = (edge[0].fX - edge[points].fX) * (edge[0].fY + edge[points].fY) ;
3630 bool sumSet = false;
3630 if (fVerb == SkPath::kCubic_Verb) { 3631 if (fVerb == SkPath::kCubic_Verb) {
3632 SkDCubic cubic;
3633 cubic.set(edge);
3634 double inflectionTs[2];
3635 int inflections = cubic.findInflections(inflectionTs);
3636 // FIXME: this fixes cubicOp114 and breaks cubicOp58d
3637 // the trouble is that cubics with inflections confuse whether the curve breaks towards
3638 // or away, which in turn is used to determine if it is on the far right or left.
3639 // Probably a totally different approach is in order. At one time I trie d to project a
3640 // horizontal ray to determine winding, but was confused by how to map t he vertically
3641 // oriented winding computation over.
3642 if (0 && inflections) {
3643 double tLo = this->span(tStart).fT;
3644 double tHi = this->span(tEnd).fT;
3645 double tLoStart = tLo;
3646 for (int index = 0; index < inflections; ++index) {
3647 if (between(tLo, inflectionTs[index], tHi)) {
3648 tLo = inflectionTs[index];
3649 }
3650 }
3651 if (tLo != tLoStart && tLo != tHi) {
3652 SkDPoint sub[2];
3653 sub[0] = cubic.ptAtT(tLo);
3654 sub[1].set(edge[3]);
3655 SkDPoint ctrl[2];
3656 SkDCubic::SubDivide(fPts, sub[0], sub[1], tLo, tHi, ctrl);
3657 edge[0] = sub[0].asSkPoint();
3658 edge[1] = ctrl[0].asSkPoint();
3659 edge[2] = ctrl[1].asSkPoint();
3660 sum = (edge[0].fX - edge[3].fX) * (edge[0].fY + edge[3].fY);
3661 }
3662 }
3631 SkScalar lesser = SkTMin<SkScalar>(edge[0].fY, edge[3].fY); 3663 SkScalar lesser = SkTMin<SkScalar>(edge[0].fY, edge[3].fY);
3632 if (edge[1].fY < lesser && edge[2].fY < lesser) { 3664 if (edge[1].fY < lesser && edge[2].fY < lesser) {
3633 SkDLine tangent1 = {{ {edge[0].fX, edge[0].fY}, {edge[1].fX, edge[1] .fY} }}; 3665 SkDLine tangent1 = {{ {edge[0].fX, edge[0].fY}, {edge[1].fX, edge[1] .fY} }};
3634 SkDLine tangent2 = {{ {edge[2].fX, edge[2].fY}, {edge[3].fX, edge[3] .fY} }}; 3666 SkDLine tangent2 = {{ {edge[2].fX, edge[2].fY}, {edge[3].fX, edge[3] .fY} }};
3635 if (SkIntersections::Test(tangent1, tangent2)) { 3667 if (SkIntersections::Test(tangent1, tangent2)) {
3636 SkPoint topPt = cubic_top(fPts, fTs[tStart].fT, fTs[tEnd].fT); 3668 SkPoint topPt = cubic_top(fPts, fTs[tStart].fT, fTs[tEnd].fT);
3637 sum += (topPt.fX - edge[0].fX) * (topPt.fY + edge[0].fY); 3669 sum += (topPt.fX - edge[0].fX) * (topPt.fY + edge[0].fY);
3638 sum += (edge[3].fX - topPt.fX) * (edge[3].fY + topPt.fY); 3670 sum += (edge[3].fX - topPt.fX) * (edge[3].fY + topPt.fY);
3639 return sum <= 0; 3671 sumSet = true;
3640 } 3672 }
3641 } 3673 }
3642 } 3674 }
3643 for (int idx = 0; idx < points; ++idx){ 3675 if (!sumSet) {
3644 sum += (edge[idx + 1].fX - edge[idx].fX) * (edge[idx + 1].fY + edge[idx] .fY); 3676 for (int idx = 0; idx < points; ++idx){
3677 sum += (edge[idx + 1].fX - edge[idx].fX) * (edge[idx + 1].fY + edge[ idx].fY);
3678 }
3679 }
3680 if (fVerb == SkPath::kCubic_Verb) {
3681 SkDCubic cubic;
3682 cubic.set(edge);
3683 *swap = sum > 0 && !cubic.monotonicInY() && !cubic.serpentine();
3684 } else {
3685 SkDQuad quad;
3686 quad.set(edge);
3687 *swap = sum > 0 && !quad.monotonicInY();
3645 } 3688 }
3646 return sum <= 0; 3689 return sum <= 0;
3647 } 3690 }
3648 3691
3649 bool SkOpSegment::monotonicInY(int tStart, int tEnd) const { 3692 bool SkOpSegment::monotonicInY(int tStart, int tEnd) const {
3650 SkASSERT(fVerb != SkPath::kLine_Verb); 3693 SkASSERT(fVerb != SkPath::kLine_Verb);
3651 if (fVerb == SkPath::kQuad_Verb) { 3694 if (fVerb == SkPath::kQuad_Verb) {
3652 SkDQuad dst = SkDQuad::SubDivide(fPts, fTs[tStart].fT, fTs[tEnd].fT); 3695 SkDQuad dst = SkDQuad::SubDivide(fPts, fTs[tStart].fT, fTs[tEnd].fT);
3653 return dst.monotonicInY(); 3696 return dst.monotonicInY();
3654 } 3697 }
(...skipping 638 matching lines...) Expand 10 before | Expand all | Expand 10 after
4293 SkASSERT(span->fWindValue > 0 || span->fOppValue != 0); 4336 SkASSERT(span->fWindValue > 0 || span->fOppValue != 0);
4294 span->fWindValue = 0; 4337 span->fWindValue = 0;
4295 span->fOppValue = 0; 4338 span->fOppValue = 0;
4296 if (span->fTiny || span->fSmall) { 4339 if (span->fTiny || span->fSmall) {
4297 return; 4340 return;
4298 } 4341 }
4299 SkASSERT(!span->fDone); 4342 SkASSERT(!span->fDone);
4300 span->fDone = true; 4343 span->fDone = true;
4301 ++fDoneSpans; 4344 ++fDoneSpans;
4302 } 4345 }
OLDNEW
« no previous file with comments | « src/pathops/SkOpSegment.h ('k') | src/pathops/SkPathOpsDebug.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698