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 |