| 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 "SkOpCoincidence.h" | 7 #include "SkOpCoincidence.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 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 } | 95 } |
| 96 | 96 |
| 97 SkOpAngle* SkOpSegment::activeAngleOther(SkOpSpanBase* start, SkOpSpanBase** sta
rtPtr, | 97 SkOpAngle* SkOpSegment::activeAngleOther(SkOpSpanBase* start, SkOpSpanBase** sta
rtPtr, |
| 98 SkOpSpanBase** endPtr, bool* done, bool* sortable) { | 98 SkOpSpanBase** endPtr, bool* done, bool* sortable) { |
| 99 SkOpPtT* oPtT = start->ptT()->next(); | 99 SkOpPtT* oPtT = start->ptT()->next(); |
| 100 SkOpSegment* other = oPtT->segment(); | 100 SkOpSegment* other = oPtT->segment(); |
| 101 SkOpSpanBase* oSpan = oPtT->span(); | 101 SkOpSpanBase* oSpan = oPtT->span(); |
| 102 return other->activeAngleInner(oSpan, startPtr, endPtr, done, sortable); | 102 return other->activeAngleInner(oSpan, startPtr, endPtr, done, sortable); |
| 103 } | 103 } |
| 104 | 104 |
| 105 SkPoint SkOpSegment::activeLeftTop(SkOpSpanBase** firstSpan) { | 105 SkDPoint SkOpSegment::activeLeftTop(SkOpSpanBase** firstSpan) { |
| 106 SkASSERT(!done()); | 106 SkASSERT(!done()); |
| 107 SkPoint topPt = {SK_ScalarMax, SK_ScalarMax}; | 107 SkDPoint topPt = {SK_ScalarMax, SK_ScalarMax}; |
| 108 // see if either end is not done since we want smaller Y of the pair | 108 // see if either end is not done since we want smaller Y of the pair |
| 109 bool lastDone = true; | 109 bool lastDone = true; |
| 110 SkOpSpanBase* span = &fHead; | 110 SkOpSpanBase* span = &fHead; |
| 111 SkOpSpanBase* lastSpan = NULL; | 111 SkOpSpanBase* lastSpan = NULL; |
| 112 do { | 112 do { |
| 113 if (!lastDone || (!span->final() && !span->upCast()->done())) { | 113 if (!lastDone || (!span->final() && !span->upCast()->done())) { |
| 114 const SkPoint& xy = span->pt(); | 114 const SkPoint& xy = span->pt(); |
| 115 if (topPt.fY > xy.fY || (topPt.fY == xy.fY && topPt.fX > xy.fX)) { | 115 if (topPt.fY > xy.fY || (topPt.fY == xy.fY && topPt.fX > xy.fX)) { |
| 116 topPt = xy; | 116 topPt = xy; |
| 117 if (firstSpan) { | 117 if (firstSpan) { |
| 118 *firstSpan = span; | 118 *firstSpan = span; |
| 119 } | 119 } |
| 120 } | 120 } |
| 121 if (fVerb != SkPath::kLine_Verb && !lastDone | 121 if (fVerb != SkPath::kLine_Verb && !lastDone) { |
| 122 && fCubicType != SkDCubic::kSplitAtMaxCurvature_SkDCubicType
) { | |
| 123 double curveTopT; | 122 double curveTopT; |
| 124 SkPoint curveTop = (*CurveTop[fVerb])(fPts, fWeight, lastSpan->t
(), span->t(), | 123 SkDCurve curve; |
| 124 this->subDivide(lastSpan, span, &curve); |
| 125 SkDPoint curveTop = (curve.*Top[fVerb])(fPts, fWeight, lastSpan-
>t(), span->t(), |
| 125 &curveTopT); | 126 &curveTopT); |
| 126 if (topPt.fY > curveTop.fY || (topPt.fY == curveTop.fY && topPt.
fX > curveTop.fX)) { | 127 if (topPt.fY > curveTop.fY || (topPt.fY == curveTop.fY && topPt.
fX > curveTop.fX)) { |
| 127 topPt = curveTop; | 128 topPt = curveTop; |
| 128 if (firstSpan) { | 129 if (firstSpan) { |
| 129 const SkPoint& lastXY = lastSpan->pt(); | 130 const SkPoint& lastXY = lastSpan->pt(); |
| 130 *firstSpan = lastXY.fY > xy.fY || (lastXY.fY == xy.fY &&
lastXY.fX > xy.fX) | 131 *firstSpan = lastXY.fY > xy.fY || (lastXY.fY == xy.fY &&
lastXY.fX > xy.fX) |
| 131 ? span : lastSpan; | 132 ? span : lastSpan; |
| 132 } | 133 } |
| 133 } | 134 } |
| 134 } | 135 } |
| (...skipping 950 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1085 const SkOpAngle* angle = baseAngle; | 1086 const SkOpAngle* angle = baseAngle; |
| 1086 #if DEBUG_SWAP_TOP | 1087 #if DEBUG_SWAP_TOP |
| 1087 SkDebugf("-%s- baseAngle\n", __FUNCTION__); | 1088 SkDebugf("-%s- baseAngle\n", __FUNCTION__); |
| 1088 baseAngle->debugLoop(); | 1089 baseAngle->debugLoop(); |
| 1089 #endif | 1090 #endif |
| 1090 do { | 1091 do { |
| 1091 if (!angle->unorderable()) { | 1092 if (!angle->unorderable()) { |
| 1092 const SkOpSegment* next = angle->segment(); | 1093 const SkOpSegment* next = angle->segment(); |
| 1093 SkPathOpsBounds bounds; | 1094 SkPathOpsBounds bounds; |
| 1094 next->subDivideBounds(angle->end(), angle->start(), &bounds); | 1095 next->subDivideBounds(angle->end(), angle->start(), &bounds); |
| 1095 bool nearSame = AlmostEqualUlps(top, bounds.top()); | 1096 if (top > bounds.fTop) { |
| 1096 bool lowerSector = !firstAngle || angle->sectorEnd() < firstAngle->s
ectorStart(); | |
| 1097 bool lesserSector = top > bounds.fTop; | |
| 1098 if (lesserSector && (!nearSame || lowerSector)) { | |
| 1099 top = bounds.fTop; | 1097 top = bounds.fTop; |
| 1100 firstAngle = angle; | 1098 firstAngle = angle; |
| 1101 } | 1099 } |
| 1102 } | 1100 } |
| 1103 angle = angle->next(); | 1101 angle = angle->next(); |
| 1104 } while (angle != baseAngle); | 1102 } while (angle != baseAngle); |
| 1105 if (!firstAngle) { | 1103 if (!firstAngle) { |
| 1106 return NULL; // if all are unorderable, give up | 1104 return NULL; // if all are unorderable, give up |
| 1107 } | 1105 } |
| 1108 #if DEBUG_SWAP_TOP | 1106 #if DEBUG_SWAP_TOP |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1445 if (fVerb == SkPath::kQuad_Verb) { | 1443 if (fVerb == SkPath::kQuad_Verb) { |
| 1446 SkDQuad dst = SkDQuad::SubDivide(fPts, start->t(), end->t()); | 1444 SkDQuad dst = SkDQuad::SubDivide(fPts, start->t(), end->t()); |
| 1447 return dst.monotonicInY(); | 1445 return dst.monotonicInY(); |
| 1448 } | 1446 } |
| 1449 if (fVerb == SkPath::kConic_Verb) { | 1447 if (fVerb == SkPath::kConic_Verb) { |
| 1450 SkDConic dst = SkDConic::SubDivide(fPts, fWeight, start->t(), end->t()); | 1448 SkDConic dst = SkDConic::SubDivide(fPts, fWeight, start->t(), end->t()); |
| 1451 return dst.monotonicInY(); | 1449 return dst.monotonicInY(); |
| 1452 } | 1450 } |
| 1453 SkASSERT(fVerb == SkPath::kCubic_Verb); | 1451 SkASSERT(fVerb == SkPath::kCubic_Verb); |
| 1454 SkDCubic dst = SkDCubic::SubDivide(fPts, start->t(), end->t()); | 1452 SkDCubic dst = SkDCubic::SubDivide(fPts, start->t(), end->t()); |
| 1455 return dst.monotonicInY(); | 1453 if (dst.monotonicInY()) { |
| 1454 return true; |
| 1455 } |
| 1456 SkDCubic whole; |
| 1457 whole.set(fPts); |
| 1458 return whole.monotonicInY(); |
| 1456 } | 1459 } |
| 1457 | 1460 |
| 1458 bool SkOpSegment::NextCandidate(SkOpSpanBase* span, SkOpSpanBase** start, | 1461 bool SkOpSegment::NextCandidate(SkOpSpanBase* span, SkOpSpanBase** start, |
| 1459 SkOpSpanBase** end) { | 1462 SkOpSpanBase** end) { |
| 1460 while (span->final() || span->upCast()->done()) { | 1463 while (span->final() || span->upCast()->done()) { |
| 1461 if (span->final()) { | 1464 if (span->final()) { |
| 1462 return false; | 1465 return false; |
| 1463 } | 1466 } |
| 1464 span = span->upCast()->next(); | 1467 span = span->upCast()->next(); |
| 1465 } | 1468 } |
| (...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2016 startT, endT, &edge->fConic.fWeight); | 2019 startT, endT, &edge->fConic.fWeight); |
| 2017 } else { | 2020 } else { |
| 2018 SkASSERT(fVerb == SkPath::kCubic_Verb); | 2021 SkASSERT(fVerb == SkPath::kCubic_Verb); |
| 2019 SkDCubic::SubDivide(fPts, edge->fCubic[0], edge->fCubic[3], startT, endT
, &edge->fCubic[1]); | 2022 SkDCubic::SubDivide(fPts, edge->fCubic[0], edge->fCubic[3], startT, endT
, &edge->fCubic[1]); |
| 2020 } | 2023 } |
| 2021 return true; | 2024 return true; |
| 2022 } | 2025 } |
| 2023 | 2026 |
| 2024 void SkOpSegment::subDivideBounds(const SkOpSpanBase* start, const SkOpSpanBase*
end, | 2027 void SkOpSegment::subDivideBounds(const SkOpSpanBase* start, const SkOpSpanBase*
end, |
| 2025 SkPathOpsBounds* bounds) const { | 2028 SkPathOpsBounds* bounds) const { |
| 2026 SkOpCurve edge; | 2029 SkDCurve edge; |
| 2027 subDivide(start, end, &edge); | 2030 subDivide(start, end, &edge); |
| 2028 (bounds->*SetCurveBounds[fVerb])(edge.fPts, edge.fWeight); | 2031 (edge.*SetBounds[fVerb])(fPts, fWeight, start->t(), end->t(), bounds); |
| 2032 } |
| 2033 |
| 2034 SkDPoint SkOpSegment::top(const SkOpSpanBase* start, const SkOpSpanBase* end, do
uble* topT) const { |
| 2035 SkDCurve edge; |
| 2036 subDivide(start, end, &edge); |
| 2037 return (edge.*Top[fVerb])(fPts, fWeight, start->t(), end->t(), topT); |
| 2029 } | 2038 } |
| 2030 | 2039 |
| 2031 void SkOpSegment::undoneSpan(SkOpSpanBase** start, SkOpSpanBase** end) { | 2040 void SkOpSegment::undoneSpan(SkOpSpanBase** start, SkOpSpanBase** end) { |
| 2032 SkOpSpan* span = this->head(); | 2041 SkOpSpan* span = this->head(); |
| 2033 do { | 2042 do { |
| 2034 if (!span->done()) { | 2043 if (!span->done()) { |
| 2035 break; | 2044 break; |
| 2036 } | 2045 } |
| 2037 } while ((span = span->next()->upCastable())); | 2046 } while ((span = span->next()->upCastable())); |
| 2038 SkASSERT(span); | 2047 SkASSERT(span); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2133 #if DEBUG_WINDING_AT_T | 2142 #if DEBUG_WINDING_AT_T |
| 2134 SkDebugf(" dx=%c winding=%d\n", *dx > 0 ? '+' : '-', winding); | 2143 SkDebugf(" dx=%c winding=%d\n", *dx > 0 ? '+' : '-', winding); |
| 2135 #endif | 2144 #endif |
| 2136 return winding; | 2145 return winding; |
| 2137 } | 2146 } |
| 2138 | 2147 |
| 2139 int SkOpSegment::windSum(const SkOpAngle* angle) const { | 2148 int SkOpSegment::windSum(const SkOpAngle* angle) const { |
| 2140 const SkOpSpan* minSpan = angle->start()->starter(angle->end()); | 2149 const SkOpSpan* minSpan = angle->start()->starter(angle->end()); |
| 2141 return minSpan->windSum(); | 2150 return minSpan->windSum(); |
| 2142 } | 2151 } |
| OLD | NEW |