| 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 "SkIntersections.h" | |
| 8 #include "SkOpAngle.h" | 7 #include "SkOpAngle.h" |
| 9 #include "SkOpSegment.h" | 8 #include "SkOpSegment.h" |
| 10 #include "SkPathOpsCurve.h" | 9 #include "SkPathOpsCurve.h" |
| 11 #include "SkTSort.h" | 10 #include "SkTSort.h" |
| 12 | 11 |
| 13 #if DEBUG_ANGLE | |
| 14 #include "SkString.h" | |
| 15 #endif | |
| 16 | |
| 17 /* Angles are sorted counterclockwise. The smallest angle has a positive x and t
he smallest | 12 /* Angles are sorted counterclockwise. The smallest angle has a positive x and t
he smallest |
| 18 positive y. The largest angle has a positive x and a zero y. */ | 13 positive y. The largest angle has a positive x and a zero y. */ |
| 19 | 14 |
| 20 #if DEBUG_ANGLE | 15 #if DEBUG_ANGLE |
| 21 static bool CompareResult(SkString* bugOut, int append, bool compare) { | 16 static bool CompareResult(const char* func, SkString* bugOut, SkString* bugP
art, int append, |
| 17 bool compare) { |
| 22 SkDebugf("%s %c %d\n", bugOut->c_str(), compare ? 'T' : 'F', append); | 18 SkDebugf("%s %c %d\n", bugOut->c_str(), compare ? 'T' : 'F', append); |
| 19 SkDebugf("%sPart %s\n", func, bugPart[0].c_str()); |
| 20 SkDebugf("%sPart %s\n", func, bugPart[1].c_str()); |
| 21 SkDebugf("%sPart %s\n", func, bugPart[2].c_str()); |
| 23 return compare; | 22 return compare; |
| 24 } | 23 } |
| 25 | 24 |
| 26 #define COMPARE_RESULT(append, compare) CompareResult(&bugOut, append, compa
re) | 25 #define COMPARE_RESULT(append, compare) CompareResult(__FUNCTION__, &bugOut,
bugPart, append, \ |
| 26 compare) |
| 27 #else | 27 #else |
| 28 #define COMPARE_RESULT(append, compare) compare | 28 #define COMPARE_RESULT(append, compare) compare |
| 29 #endif | 29 #endif |
| 30 | 30 |
| 31 /* quarter angle values for sector | 31 /* quarter angle values for sector |
| 32 | 32 |
| 33 31 x > 0, y == 0 horizontal line (to the right) | 33 31 x > 0, y == 0 horizontal line (to the right) |
| 34 0 x > 0, y == epsilon quad/cubic horizontal tangent eventually going +
y | 34 0 x > 0, y == epsilon quad/cubic horizontal tangent eventually going +
y |
| 35 1 x > 0, y > 0, x > y nearer horizontal angle | 35 1 x > 0, y > 0, x > y nearer horizontal angle |
| 36 2 x + e == y quad/cubic 45 going horiz | 36 2 x + e == y quad/cubic 45 going horiz |
| (...skipping 14 matching lines...) Expand all Loading... |
| 51 16 | 30 | 51 16 | 30 |
| 52 17 | 29 | 52 17 | 29 |
| 53 18 / | \ 28 | 53 18 / | \ 28 |
| 54 19 | 27 | 54 19 | 27 |
| 55 20 | 26 | 55 20 | 26 |
| 56 21 | 25 | 56 21 | 25 |
| 57 22 23 24 | 57 22 23 24 |
| 58 */ | 58 */ |
| 59 | 59 |
| 60 // return true if lh < this < rh | 60 // return true if lh < this < rh |
| 61 bool SkOpAngle::after(const SkOpAngle* test) const { | 61 bool SkOpAngle::after(SkOpAngle* test) { |
| 62 const SkOpAngle& lh = *test; | 62 SkOpAngle* lh = test; |
| 63 const SkOpAngle& rh = *lh.fNext; | 63 SkOpAngle* rh = lh->fNext; |
| 64 SkASSERT(&lh != &rh); | 64 SkASSERT(lh != rh); |
| 65 #if DEBUG_ANGLE | 65 #if DEBUG_ANGLE |
| 66 SkString bugOut; | 66 SkString bugOut; |
| 67 bugOut.printf("%s [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g" | 67 bugOut.printf("%s [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g" |
| 68 " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g" | 68 " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g" |
| 69 " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g ", __FUNCTION__, | 69 " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g ", __FUNCTION__, |
| 70 lh.fSegment->debugID(), lh.debugID(), lh.fSectorStart, lh.fSectorEnd
, | 70 lh->segment()->debugID(), lh->debugID(), lh->fSectorStart, lh->fSect
orEnd, |
| 71 lh.fSegment->t(lh.fStart), lh.fSegment->t(lh.fEnd), | 71 lh->fStart->t(), lh->fEnd->t(), |
| 72 fSegment->debugID(), debugID(), fSectorStart, fSectorEnd, fSegment->
t(fStart), | 72 segment()->debugID(), debugID(), fSectorStart, fSectorEnd, fStart->t
(), fEnd->t(), |
| 73 fSegment->t(fEnd), | 73 rh->segment()->debugID(), rh->debugID(), rh->fSectorStart, rh->fSect
orEnd, |
| 74 rh.fSegment->debugID(), rh.debugID(), rh.fSectorStart, rh.fSectorEnd
, | 74 rh->fStart->t(), rh->fEnd->t()); |
| 75 rh.fSegment->t(rh.fStart), rh.fSegment->t(rh.fEnd)); | 75 SkString bugPart[3] = { lh->debugPart(), this->debugPart(), rh->debugPart()
}; |
| 76 #endif | 76 #endif |
| 77 if (lh.fComputeSector && !const_cast<SkOpAngle&>(lh).computeSector()) { | 77 if (lh->fComputeSector && !lh->computeSector()) { |
| 78 return COMPARE_RESULT(1, true); | 78 return COMPARE_RESULT(1, true); |
| 79 } | 79 } |
| 80 if (fComputeSector && !const_cast<SkOpAngle*>(this)->computeSector()) { | 80 if (fComputeSector && !this->computeSector()) { |
| 81 return COMPARE_RESULT(2, true); | 81 return COMPARE_RESULT(2, true); |
| 82 } | 82 } |
| 83 if (rh.fComputeSector && !const_cast<SkOpAngle&>(rh).computeSector()) { | 83 if (rh->fComputeSector && !rh->computeSector()) { |
| 84 return COMPARE_RESULT(3, true); | 84 return COMPARE_RESULT(3, true); |
| 85 } | 85 } |
| 86 #if DEBUG_ANGLE // reset bugOut with computed sectors | 86 #if DEBUG_ANGLE // reset bugOut with computed sectors |
| 87 bugOut.printf("%s [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g" | 87 bugOut.printf("%s [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g" |
| 88 " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g" | 88 " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g" |
| 89 " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g ", __FUNCTION__, | 89 " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g ", __FUNCTION__, |
| 90 lh.fSegment->debugID(), lh.debugID(), lh.fSectorStart, lh.fSectorEnd
, | 90 lh->segment()->debugID(), lh->debugID(), lh->fSectorStart, lh->fSect
orEnd, |
| 91 lh.fSegment->t(lh.fStart), lh.fSegment->t(lh.fEnd), | 91 lh->fStart->t(), lh->fEnd->t(), |
| 92 fSegment->debugID(), debugID(), fSectorStart, fSectorEnd, fSegment->
t(fStart), | 92 segment()->debugID(), debugID(), fSectorStart, fSectorEnd, fStart->t
(), fEnd->t(), |
| 93 fSegment->t(fEnd), | 93 rh->segment()->debugID(), rh->debugID(), rh->fSectorStart, rh->fSect
orEnd, |
| 94 rh.fSegment->debugID(), rh.debugID(), rh.fSectorStart, rh.fSectorEnd
, | 94 rh->fStart->t(), rh->fEnd->t()); |
| 95 rh.fSegment->t(rh.fStart), rh.fSegment->t(rh.fEnd)); | |
| 96 #endif | 95 #endif |
| 97 bool ltrOverlap = (lh.fSectorMask | rh.fSectorMask) & fSectorMask; | 96 bool ltrOverlap = (lh->fSectorMask | rh->fSectorMask) & fSectorMask; |
| 98 bool lrOverlap = lh.fSectorMask & rh.fSectorMask; | 97 bool lrOverlap = lh->fSectorMask & rh->fSectorMask; |
| 99 int lrOrder; // set to -1 if either order works | 98 int lrOrder; // set to -1 if either order works |
| 100 if (!lrOverlap) { // no lh/rh sector overlap | 99 if (!lrOverlap) { // no lh/rh sector overlap |
| 101 if (!ltrOverlap) { // no lh/this/rh sector overlap | 100 if (!ltrOverlap) { // no lh/this/rh sector overlap |
| 102 return COMPARE_RESULT(4, (lh.fSectorEnd > rh.fSectorStart) | 101 return COMPARE_RESULT(4, (lh->fSectorEnd > rh->fSectorStart) |
| 103 ^ (fSectorStart > lh.fSectorEnd) ^ (fSectorStart > rh.fSecto
rStart)); | 102 ^ (fSectorStart > lh->fSectorEnd) ^ (fSectorStart > rh->fSec
torStart)); |
| 104 } | 103 } |
| 105 int lrGap = (rh.fSectorStart - lh.fSectorStart + 32) & 0x1f; | 104 int lrGap = (rh->fSectorStart - lh->fSectorStart + 32) & 0x1f; |
| 106 /* A tiny change can move the start +/- 4. The order can only be determi
ned if | 105 /* A tiny change can move the start +/- 4. The order can only be determi
ned if |
| 107 lr gap is not 12 to 20 or -12 to -20. | 106 lr gap is not 12 to 20 or -12 to -20. |
| 108 -31 ..-21 1 | 107 -31 ..-21 1 |
| 109 -20 ..-12 -1 | 108 -20 ..-12 -1 |
| 110 -11 .. -1 0 | 109 -11 .. -1 0 |
| 111 0 shouldn't get here | 110 0 shouldn't get here |
| 112 11 .. 1 1 | 111 11 .. 1 1 |
| 113 12 .. 20 -1 | 112 12 .. 20 -1 |
| 114 21 .. 31 0 | 113 21 .. 31 0 |
| 115 */ | 114 */ |
| 116 lrOrder = lrGap > 20 ? 0 : lrGap > 11 ? -1 : 1; | 115 lrOrder = lrGap > 20 ? 0 : lrGap > 11 ? -1 : 1; |
| 117 } else { | 116 } else { |
| 118 lrOrder = (int) lh.orderable(rh); | 117 lrOrder = (int) lh->orderable(rh); |
| 119 if (!ltrOverlap) { | 118 if (!ltrOverlap) { |
| 120 return COMPARE_RESULT(5, !lrOrder); | 119 return COMPARE_RESULT(5, !lrOrder); |
| 121 } | 120 } |
| 122 } | 121 } |
| 123 int ltOrder; | 122 int ltOrder; |
| 124 SkASSERT((lh.fSectorMask & fSectorMask) || (rh.fSectorMask & fSectorMask)); | 123 SkASSERT((lh->fSectorMask & fSectorMask) || (rh->fSectorMask & fSectorMask))
; |
| 125 if (lh.fSectorMask & fSectorMask) { | 124 if (lh->fSectorMask & fSectorMask) { |
| 126 ltOrder = (int) lh.orderable(*this); | 125 ltOrder = (int) lh->orderable(this); |
| 127 } else { | 126 } else { |
| 128 int ltGap = (fSectorStart - lh.fSectorStart + 32) & 0x1f; | 127 int ltGap = (fSectorStart - lh->fSectorStart + 32) & 0x1f; |
| 129 ltOrder = ltGap > 20 ? 0 : ltGap > 11 ? -1 : 1; | 128 ltOrder = ltGap > 20 ? 0 : ltGap > 11 ? -1 : 1; |
| 130 } | 129 } |
| 131 int trOrder; | 130 int trOrder; |
| 132 if (rh.fSectorMask & fSectorMask) { | 131 if (rh->fSectorMask & fSectorMask) { |
| 133 trOrder = (int) orderable(rh); | 132 trOrder = (int) orderable(rh); |
| 134 } else { | 133 } else { |
| 135 int trGap = (rh.fSectorStart - fSectorStart + 32) & 0x1f; | 134 int trGap = (rh->fSectorStart - fSectorStart + 32) & 0x1f; |
| 136 trOrder = trGap > 20 ? 0 : trGap > 11 ? -1 : 1; | 135 trOrder = trGap > 20 ? 0 : trGap > 11 ? -1 : 1; |
| 137 } | 136 } |
| 138 if (lrOrder >= 0 && ltOrder >= 0 && trOrder >= 0) { | 137 if (lrOrder >= 0 && ltOrder >= 0 && trOrder >= 0) { |
| 139 return COMPARE_RESULT(7, lrOrder ? (ltOrder & trOrder) : (ltOrder | trOr
der)); | 138 return COMPARE_RESULT(7, lrOrder ? (ltOrder & trOrder) : (ltOrder | trOr
der)); |
| 140 } | 139 } |
| 141 SkASSERT(lrOrder >= 0 || ltOrder >= 0 || trOrder >= 0); | 140 SkASSERT(lrOrder >= 0 || ltOrder >= 0 || trOrder >= 0); |
| 142 // There's not enough information to sort. Get the pairs of angles in opposite p
lanes. | 141 // There's not enough information to sort. Get the pairs of angles in opposite p
lanes. |
| 143 // If an order is < 0, the pair is already in an opposite plane. Check the remai
ning pairs. | 142 // If an order is < 0, the pair is already in an opposite plane. Check the remai
ning pairs. |
| 144 // FIXME : once all variants are understood, rewrite this more simply | 143 // FIXME : once all variants are understood, rewrite this more simply |
| 145 if (ltOrder == 0 && lrOrder == 0) { | 144 if (ltOrder == 0 && lrOrder == 0) { |
| 146 SkASSERT(trOrder < 0); | 145 SkASSERT(trOrder < 0); |
| 147 // FIXME : once this is verified to work, remove one opposite angle call | 146 // FIXME : once this is verified to work, remove one opposite angle call |
| 148 SkDEBUGCODE(bool lrOpposite = lh.oppositePlanes(rh)); | 147 SkDEBUGCODE(bool lrOpposite = lh->oppositePlanes(rh)); |
| 149 bool ltOpposite = lh.oppositePlanes(*this); | 148 bool ltOpposite = lh->oppositePlanes(this); |
| 150 SkASSERT(lrOpposite != ltOpposite); | 149 SkASSERT(lrOpposite != ltOpposite); |
| 151 return COMPARE_RESULT(8, ltOpposite); | 150 return COMPARE_RESULT(8, ltOpposite); |
| 152 } else if (ltOrder == 1 && trOrder == 0) { | 151 } else if (ltOrder == 1 && trOrder == 0) { |
| 153 SkASSERT(lrOrder < 0); | 152 SkASSERT(lrOrder < 0); |
| 154 SkDEBUGCODE(bool ltOpposite = lh.oppositePlanes(*this)); | 153 SkDEBUGCODE(bool ltOpposite = lh->oppositePlanes(this)); |
| 155 bool trOpposite = oppositePlanes(rh); | 154 bool trOpposite = oppositePlanes(rh); |
| 156 SkASSERT(ltOpposite != trOpposite); | 155 SkASSERT(ltOpposite != trOpposite); |
| 157 return COMPARE_RESULT(9, trOpposite); | 156 return COMPARE_RESULT(9, trOpposite); |
| 158 } else if (lrOrder == 1 && trOrder == 1) { | 157 } else if (lrOrder == 1 && trOrder == 1) { |
| 159 SkASSERT(ltOrder < 0); | 158 SkASSERT(ltOrder < 0); |
| 160 SkDEBUGCODE(bool trOpposite = oppositePlanes(rh)); | 159 SkDEBUGCODE(bool trOpposite = oppositePlanes(rh)); |
| 161 bool lrOpposite = lh.oppositePlanes(rh); | 160 bool lrOpposite = lh->oppositePlanes(rh); |
| 162 SkASSERT(lrOpposite != trOpposite); | 161 SkASSERT(lrOpposite != trOpposite); |
| 163 return COMPARE_RESULT(10, lrOpposite); | 162 return COMPARE_RESULT(10, lrOpposite); |
| 164 } | 163 } |
| 165 if (lrOrder < 0) { | 164 if (lrOrder < 0) { |
| 166 if (ltOrder < 0) { | 165 if (ltOrder < 0) { |
| 167 return COMPARE_RESULT(11, trOrder); | 166 return COMPARE_RESULT(11, trOrder); |
| 168 } | 167 } |
| 169 return COMPARE_RESULT(12, ltOrder); | 168 return COMPARE_RESULT(12, ltOrder); |
| 170 } | 169 } |
| 171 return COMPARE_RESULT(13, !lrOrder); | 170 return COMPARE_RESULT(13, !lrOrder); |
| 172 } | 171 } |
| 173 | 172 |
| 174 // given a line, see if the opposite curve's convex hull is all on one side | 173 // given a line, see if the opposite curve's convex hull is all on one side |
| 175 // returns -1=not on one side 0=this CW of test 1=this CCW of test | 174 // returns -1=not on one side 0=this CW of test 1=this CCW of test |
| 176 int SkOpAngle::allOnOneSide(const SkOpAngle& test) const { | 175 int SkOpAngle::allOnOneSide(const SkOpAngle* test) { |
| 177 SkASSERT(!fIsCurve); | 176 SkASSERT(!fIsCurve); |
| 178 SkASSERT(test.fIsCurve); | 177 SkASSERT(test->fIsCurve); |
| 179 const SkDPoint& origin = test.fCurvePart[0]; | 178 const SkDPoint& origin = test->fCurvePart[0]; |
| 180 SkVector line; | 179 SkVector line; |
| 181 if (fSegment->verb() == SkPath::kLine_Verb) { | 180 if (segment()->verb() == SkPath::kLine_Verb) { |
| 182 const SkPoint* linePts = fSegment->pts(); | 181 const SkPoint* linePts = segment()->pts(); |
| 183 int lineStart = fStart < fEnd ? 0 : 1; | 182 int lineStart = fStart->t() < fEnd->t() ? 0 : 1; |
| 184 line = linePts[lineStart ^ 1] - linePts[lineStart]; | 183 line = linePts[lineStart ^ 1] - linePts[lineStart]; |
| 185 } else { | 184 } else { |
| 186 SkPoint shortPts[2] = { fCurvePart[0].asSkPoint(), fCurvePart[1].asSkPoi
nt() }; | 185 SkPoint shortPts[2] = { fCurvePart[0].asSkPoint(), fCurvePart[1].asSkPoi
nt() }; |
| 187 line = shortPts[1] - shortPts[0]; | 186 line = shortPts[1] - shortPts[0]; |
| 188 } | 187 } |
| 189 float crosses[3]; | 188 float crosses[3]; |
| 190 SkPath::Verb testVerb = test.fSegment->verb(); | 189 SkPath::Verb testVerb = test->segment()->verb(); |
| 191 int iMax = SkPathOpsVerbToPoints(testVerb); | 190 int iMax = SkPathOpsVerbToPoints(testVerb); |
| 192 // SkASSERT(origin == test.fCurveHalf[0]); | 191 // SkASSERT(origin == test.fCurveHalf[0]); |
| 193 const SkDCubic& testCurve = test.fCurvePart; | 192 const SkDCubic& testCurve = test->fCurvePart; |
| 194 // do { | 193 for (int index = 1; index <= iMax; ++index) { |
| 195 for (int index = 1; index <= iMax; ++index) { | 194 float xy1 = (float) (line.fX * (testCurve[index].fY - origin.fY)); |
| 196 float xy1 = (float) (line.fX * (testCurve[index].fY - origin.fY)); | 195 float xy2 = (float) (line.fY * (testCurve[index].fX - origin.fX)); |
| 197 float xy2 = (float) (line.fY * (testCurve[index].fX - origin.fX)); | 196 crosses[index - 1] = AlmostEqualUlps(xy1, xy2) ? 0 : xy1 - xy2; |
| 198 crosses[index - 1] = AlmostEqualUlps(xy1, xy2) ? 0 : xy1 - xy2; | 197 } |
| 199 } | 198 if (crosses[0] * crosses[1] < 0) { |
| 200 if (crosses[0] * crosses[1] < 0) { | 199 return -1; |
| 200 } |
| 201 if (SkPath::kCubic_Verb == testVerb) { |
| 202 if (crosses[0] * crosses[2] < 0 || crosses[1] * crosses[2] < 0) { |
| 201 return -1; | 203 return -1; |
| 202 } | 204 } |
| 203 if (SkPath::kCubic_Verb == testVerb) { | 205 } |
| 204 if (crosses[0] * crosses[2] < 0 || crosses[1] * crosses[2] < 0) { | 206 if (crosses[0]) { |
| 205 return -1; | 207 return crosses[0] < 0; |
| 206 } | 208 } |
| 207 } | 209 if (crosses[1]) { |
| 208 if (crosses[0]) { | 210 return crosses[1] < 0; |
| 209 return crosses[0] < 0; | 211 } |
| 210 } | 212 if (SkPath::kCubic_Verb == testVerb && crosses[2]) { |
| 211 if (crosses[1]) { | 213 return crosses[2] < 0; |
| 212 return crosses[1] < 0; | 214 } |
| 213 } | |
| 214 if (SkPath::kCubic_Verb == testVerb && crosses[2]) { | |
| 215 return crosses[2] < 0; | |
| 216 } | |
| 217 fUnorderable = true; | 215 fUnorderable = true; |
| 218 return -1; | 216 return -1; |
| 219 } | 217 } |
| 220 | 218 |
| 221 bool SkOpAngle::calcSlop(double x, double y, double rx, double ry, bool* result)
const { | |
| 222 double absX = fabs(x); | |
| 223 double absY = fabs(y); | |
| 224 double length = absX < absY ? absX / 2 + absY : absX + absY / 2; | |
| 225 int exponent; | |
| 226 (void) frexp(length, &exponent); | |
| 227 double epsilon = ldexp(FLT_EPSILON, exponent); | |
| 228 SkPath::Verb verb = fSegment->verb(); | |
| 229 SkASSERT(verb == SkPath::kQuad_Verb || verb == SkPath::kCubic_Verb); | |
| 230 // FIXME: the quad and cubic factors are made up ; determine actual values | |
| 231 double slop = verb == SkPath::kQuad_Verb ? 4 * epsilon : 512 * epsilon; | |
| 232 double xSlop = slop; | |
| 233 double ySlop = x * y < 0 ? -xSlop : xSlop; // OPTIMIZATION: use copysign / _
copysign ? | |
| 234 double x1 = x - xSlop; | |
| 235 double y1 = y + ySlop; | |
| 236 double x_ry1 = x1 * ry; | |
| 237 double rx_y1 = rx * y1; | |
| 238 *result = x_ry1 < rx_y1; | |
| 239 double x2 = x + xSlop; | |
| 240 double y2 = y - ySlop; | |
| 241 double x_ry2 = x2 * ry; | |
| 242 double rx_y2 = rx * y2; | |
| 243 bool less2 = x_ry2 < rx_y2; | |
| 244 return *result == less2; | |
| 245 } | |
| 246 | |
| 247 bool SkOpAngle::checkCrossesZero() const { | 219 bool SkOpAngle::checkCrossesZero() const { |
| 248 int start = SkTMin(fSectorStart, fSectorEnd); | 220 int start = SkTMin(fSectorStart, fSectorEnd); |
| 249 int end = SkTMax(fSectorStart, fSectorEnd); | 221 int end = SkTMax(fSectorStart, fSectorEnd); |
| 250 bool crossesZero = end - start > 16; | 222 bool crossesZero = end - start > 16; |
| 251 return crossesZero; | 223 return crossesZero; |
| 252 } | 224 } |
| 253 | 225 |
| 254 bool SkOpAngle::checkParallel(const SkOpAngle& rh) const { | 226 // loop looking for a pair of angle parts that are too close to be sorted |
| 227 /* This is called after other more simple intersection and angle sorting tests h
ave been exhausted. |
| 228 This should be rarely called -- the test below is thorough and time consuming
. |
| 229 This checks the distance between start points; the distance between |
| 230 */ |
| 231 void SkOpAngle::checkNearCoincidence() { |
| 232 SkOpAngle* test = this; |
| 233 do { |
| 234 SkOpSegment* testSegment = test->segment(); |
| 235 double testStartT = test->start()->t(); |
| 236 SkDPoint testStartPt = testSegment->dPtAtT(testStartT); |
| 237 double testEndT = test->end()->t(); |
| 238 SkDPoint testEndPt = testSegment->dPtAtT(testEndT); |
| 239 double testLenSq = testStartPt.distanceSquared(testEndPt); |
| 240 if (0) { |
| 241 SkDebugf("%s testLenSq=%1.9g id=%d\n", __FUNCTION__, testLenSq, test
Segment->debugID()); |
| 242 } |
| 243 double testMidT = (testStartT + testEndT) / 2; |
| 244 SkOpAngle* next = test; |
| 245 while ((next = next->fNext) != this) { |
| 246 SkOpSegment* nextSegment = next->segment(); |
| 247 double testMidDistSq = testSegment->distSq(testMidT, next); |
| 248 double testEndDistSq = testSegment->distSq(testEndT, next); |
| 249 double nextStartT = next->start()->t(); |
| 250 SkDPoint nextStartPt = nextSegment->dPtAtT(nextStartT); |
| 251 double distSq = testStartPt.distanceSquared(nextStartPt); |
| 252 double nextEndT = next->end()->t(); |
| 253 double nextMidT = (nextStartT + nextEndT) / 2; |
| 254 double nextMidDistSq = nextSegment->distSq(nextMidT, test); |
| 255 double nextEndDistSq = nextSegment->distSq(nextEndT, test); |
| 256 if (0) { |
| 257 SkDebugf("%s distSq=%1.9g testId=%d nextId=%d\n", __FUNCTION__,
distSq, |
| 258 testSegment->debugID(), nextSegment->debugID()); |
| 259 SkDebugf("%s testMidDistSq=%1.9g\n", __FUNCTION__, testMidDistSq
); |
| 260 SkDebugf("%s testEndDistSq=%1.9g\n", __FUNCTION__, testEndDistSq
); |
| 261 SkDebugf("%s nextMidDistSq=%1.9g\n", __FUNCTION__, nextMidDistSq
); |
| 262 SkDebugf("%s nextEndDistSq=%1.9g\n", __FUNCTION__, nextEndDistSq
); |
| 263 SkDPoint nextEndPt = nextSegment->dPtAtT(nextEndT); |
| 264 double nextLenSq = nextStartPt.distanceSquared(nextEndPt); |
| 265 SkDebugf("%s nextLenSq=%1.9g\n", __FUNCTION__, nextLenSq); |
| 266 SkDebugf("\n"); |
| 267 } |
| 268 } |
| 269 test = test->fNext; |
| 270 } while (test->fNext != this); |
| 271 } |
| 272 |
| 273 bool SkOpAngle::checkParallel(SkOpAngle* rh) { |
| 255 SkDVector scratch[2]; | 274 SkDVector scratch[2]; |
| 256 const SkDVector* sweep, * tweep; | 275 const SkDVector* sweep, * tweep; |
| 257 if (!fUnorderedSweep) { | 276 if (!this->fUnorderedSweep) { |
| 258 sweep = fSweep; | 277 sweep = this->fSweep; |
| 259 } else { | 278 } else { |
| 260 scratch[0] = fCurvePart[1] - fCurvePart[0]; | 279 scratch[0] = this->fCurvePart[1] - this->fCurvePart[0]; |
| 261 sweep = &scratch[0]; | 280 sweep = &scratch[0]; |
| 262 } | 281 } |
| 263 if (!rh.fUnorderedSweep) { | 282 if (!rh->fUnorderedSweep) { |
| 264 tweep = rh.fSweep; | 283 tweep = rh->fSweep; |
| 265 } else { | 284 } else { |
| 266 scratch[1] = rh.fCurvePart[1] - rh.fCurvePart[0]; | 285 scratch[1] = rh->fCurvePart[1] - rh->fCurvePart[0]; |
| 267 tweep = &scratch[1]; | 286 tweep = &scratch[1]; |
| 268 } | 287 } |
| 269 double s0xt0 = sweep->crossCheck(*tweep); | 288 double s0xt0 = sweep->crossCheck(*tweep); |
| 270 if (tangentsDiverge(rh, s0xt0)) { | 289 if (tangentsDiverge(rh, s0xt0)) { |
| 271 return s0xt0 < 0; | 290 return s0xt0 < 0; |
| 272 } | 291 } |
| 273 SkDVector m0 = fSegment->dPtAtT(midT()) - fCurvePart[0]; | 292 // compute the perpendicular to the endpoints and see where it intersects th
e opposite curve |
| 274 SkDVector m1 = rh.fSegment->dPtAtT(rh.midT()) - rh.fCurvePart[0]; | 293 // if the intersections within the t range, do a cross check on those |
| 294 bool inside; |
| 295 if (this->endToSide(rh, &inside)) { |
| 296 return inside; |
| 297 } |
| 298 if (rh->endToSide(this, &inside)) { |
| 299 return !inside; |
| 300 } |
| 301 if (this->midToSide(rh, &inside)) { |
| 302 return inside; |
| 303 } |
| 304 if (rh->midToSide(this, &inside)) { |
| 305 return !inside; |
| 306 } |
| 307 // compute the cross check from the mid T values (last resort) |
| 308 SkDVector m0 = segment()->dPtAtT(this->midT()) - this->fCurvePart[0]; |
| 309 SkDVector m1 = rh->segment()->dPtAtT(rh->midT()) - rh->fCurvePart[0]; |
| 275 double m0xm1 = m0.crossCheck(m1); | 310 double m0xm1 = m0.crossCheck(m1); |
| 276 if (m0xm1 == 0) { | 311 if (m0xm1 == 0) { |
| 277 fUnorderable = true; | 312 this->fUnorderable = true; |
| 278 rh.fUnorderable = true; | 313 rh->fUnorderable = true; |
| 279 return true; | 314 return true; |
| 280 } | 315 } |
| 281 return m0xm1 < 0; | 316 return m0xm1 < 0; |
| 282 } | 317 } |
| 283 | 318 |
| 284 // the original angle is too short to get meaningful sector information | 319 // the original angle is too short to get meaningful sector information |
| 285 // lengthen it until it is long enough to be meaningful or leave it unset if len
gthening it | 320 // lengthen it until it is long enough to be meaningful or leave it unset if len
gthening it |
| 286 // would cause it to intersect one of the adjacent angles | 321 // would cause it to intersect one of the adjacent angles |
| 287 bool SkOpAngle::computeSector() { | 322 bool SkOpAngle::computeSector() { |
| 288 if (fComputedSector) { | 323 if (fComputedSector) { |
| 289 return !fUnorderable; | 324 return !fUnorderable; |
| 290 } | 325 } |
| 291 // SkASSERT(fSegment->verb() != SkPath::kLine_Verb && small()); | |
| 292 fComputedSector = true; | 326 fComputedSector = true; |
| 293 int step = fStart < fEnd ? 1 : -1; | 327 bool stepUp = fStart->t() < fEnd->t(); |
| 294 int limit = step > 0 ? fSegment->count() : -1; | 328 const SkOpSpanBase* checkEnd = fEnd; |
| 295 int checkEnd = fEnd; | 329 if (checkEnd->final() && stepUp) { |
| 330 fUnorderable = true; |
| 331 return false; |
| 332 } |
| 296 do { | 333 do { |
| 297 // advance end | 334 // advance end |
| 298 const SkOpSpan& span = fSegment->span(checkEnd); | 335 const SkOpSegment* other = checkEnd->segment(); |
| 299 const SkOpSegment* other = span.fOther; | 336 const SkOpSpanBase* oSpan = other->head(); |
| 300 int oCount = other->count(); | 337 do { |
| 301 for (int oIndex = 0; oIndex < oCount; ++oIndex) { | 338 if (oSpan->segment() != segment()) { |
| 302 const SkOpSpan& oSpan = other->span(oIndex); | |
| 303 if (oSpan.fOther != fSegment) { | |
| 304 continue; | 339 continue; |
| 305 } | 340 } |
| 306 if (oSpan.fOtherIndex == checkEnd) { | 341 if (oSpan == checkEnd) { |
| 307 continue; | 342 continue; |
| 308 } | 343 } |
| 309 if (!approximately_equal(oSpan.fOtherT, span.fT)) { | 344 if (!approximately_equal(oSpan->t(), checkEnd->t())) { |
| 310 continue; | 345 continue; |
| 311 } | 346 } |
| 312 goto recomputeSector; | 347 goto recomputeSector; |
| 313 } | 348 } while (!oSpan->final() && (oSpan = oSpan->upCast()->next())); |
| 314 checkEnd += step; | 349 checkEnd = stepUp ? !checkEnd->final() |
| 315 } while (checkEnd != limit); | 350 ? checkEnd->upCast()->next() : NULL |
| 351 : checkEnd->prev(); |
| 352 } while (checkEnd); |
| 316 recomputeSector: | 353 recomputeSector: |
| 317 if (checkEnd == fEnd || checkEnd - step == fEnd) { | 354 SkOpSpanBase* computedEnd = stepUp ? checkEnd ? checkEnd->prev() : fEnd->seg
ment()->head() |
| 355 : checkEnd ? checkEnd->upCast()->next() : fEnd->segment()->tail(); |
| 356 if (checkEnd == fEnd || computedEnd == fEnd || computedEnd == fStart) { |
| 318 fUnorderable = true; | 357 fUnorderable = true; |
| 319 return false; | 358 return false; |
| 320 } | 359 } |
| 321 int saveEnd = fEnd; | 360 SkOpSpanBase* saveEnd = fEnd; |
| 322 fComputedEnd = fEnd = checkEnd - step; | 361 fComputedEnd = fEnd = computedEnd; |
| 323 setSpans(); | 362 setSpans(); |
| 324 setSector(); | 363 setSector(); |
| 325 fEnd = saveEnd; | 364 fEnd = saveEnd; |
| 326 return !fUnorderable; | 365 return !fUnorderable; |
| 327 } | 366 } |
| 328 | 367 |
| 329 // returns -1 if overlaps 0 if no overlap cw 1 if no overlap ccw | 368 int SkOpAngle::convexHullOverlaps(const SkOpAngle* rh) const { |
| 330 int SkOpAngle::convexHullOverlaps(const SkOpAngle& rh) const { | 369 const SkDVector* sweep = this->fSweep; |
| 331 const SkDVector* sweep = fSweep; | 370 const SkDVector* tweep = rh->fSweep; |
| 332 const SkDVector* tweep = rh.fSweep; | |
| 333 double s0xs1 = sweep[0].crossCheck(sweep[1]); | 371 double s0xs1 = sweep[0].crossCheck(sweep[1]); |
| 334 double s0xt0 = sweep[0].crossCheck(tweep[0]); | 372 double s0xt0 = sweep[0].crossCheck(tweep[0]); |
| 335 double s1xt0 = sweep[1].crossCheck(tweep[0]); | 373 double s1xt0 = sweep[1].crossCheck(tweep[0]); |
| 336 bool tBetweenS = s0xs1 > 0 ? s0xt0 > 0 && s1xt0 < 0 : s0xt0 < 0 && s1xt0 > 0
; | 374 bool tBetweenS = s0xs1 > 0 ? s0xt0 > 0 && s1xt0 < 0 : s0xt0 < 0 && s1xt0 > 0
; |
| 337 double s0xt1 = sweep[0].crossCheck(tweep[1]); | 375 double s0xt1 = sweep[0].crossCheck(tweep[1]); |
| 338 double s1xt1 = sweep[1].crossCheck(tweep[1]); | 376 double s1xt1 = sweep[1].crossCheck(tweep[1]); |
| 339 tBetweenS |= s0xs1 > 0 ? s0xt1 > 0 && s1xt1 < 0 : s0xt1 < 0 && s1xt1 > 0; | 377 tBetweenS |= s0xs1 > 0 ? s0xt1 > 0 && s1xt1 < 0 : s0xt1 < 0 && s1xt1 > 0; |
| 340 double t0xt1 = tweep[0].crossCheck(tweep[1]); | 378 double t0xt1 = tweep[0].crossCheck(tweep[1]); |
| 341 if (tBetweenS) { | 379 if (tBetweenS) { |
| 342 return -1; | 380 return -1; |
| 343 } | 381 } |
| 344 if ((s0xt0 == 0 && s1xt1 == 0) || (s1xt0 == 0 && s0xt1 == 0)) { // s0 to s1
equals t0 to t1 | 382 if ((s0xt0 == 0 && s1xt1 == 0) || (s1xt0 == 0 && s0xt1 == 0)) { // s0 to s1
equals t0 to t1 |
| 345 return -1; | 383 return -1; |
| 346 } | 384 } |
| 347 bool sBetweenT = t0xt1 > 0 ? s0xt0 < 0 && s0xt1 > 0 : s0xt0 > 0 && s0xt1 < 0
; | 385 bool sBetweenT = t0xt1 > 0 ? s0xt0 < 0 && s0xt1 > 0 : s0xt0 > 0 && s0xt1 < 0
; |
| 348 sBetweenT |= t0xt1 > 0 ? s1xt0 < 0 && s1xt1 > 0 : s1xt0 > 0 && s1xt1 < 0; | 386 sBetweenT |= t0xt1 > 0 ? s1xt0 < 0 && s1xt1 > 0 : s1xt0 > 0 && s1xt1 < 0; |
| 349 if (sBetweenT) { | 387 if (sBetweenT) { |
| 350 return -1; | 388 return -1; |
| 351 } | 389 } |
| 352 // if all of the sweeps are in the same half plane, then the order of any pa
ir is enough | 390 // if all of the sweeps are in the same half plane, then the order of any pa
ir is enough |
| 353 if (s0xt0 >= 0 && s0xt1 >= 0 && s1xt0 >= 0 && s1xt1 >= 0) { | 391 if (s0xt0 >= 0 && s0xt1 >= 0 && s1xt0 >= 0 && s1xt1 >= 0) { |
| 354 return 0; | 392 return 0; |
| 355 } | 393 } |
| 356 if (s0xt0 <= 0 && s0xt1 <= 0 && s1xt0 <= 0 && s1xt1 <= 0) { | 394 if (s0xt0 <= 0 && s0xt1 <= 0 && s1xt0 <= 0 && s1xt1 <= 0) { |
| 357 return 1; | 395 return 1; |
| 358 } | 396 } |
| 359 // if the outside sweeps are greater than 180 degress: | 397 // if the outside sweeps are greater than 180 degress: |
| 360 // first assume the inital tangents are the ordering | 398 // first assume the inital tangents are the ordering |
| 361 // if the midpoint direction matches the inital order, that is enough | 399 // if the midpoint direction matches the inital order, that is enough |
| 362 SkDVector m0 = fSegment->dPtAtT(midT()) - fCurvePart[0]; | 400 SkDVector m0 = this->segment()->dPtAtT(this->midT()) - this->fCurvePart[0]; |
| 363 SkDVector m1 = rh.fSegment->dPtAtT(rh.midT()) - rh.fCurvePart[0]; | 401 SkDVector m1 = rh->segment()->dPtAtT(rh->midT()) - rh->fCurvePart[0]; |
| 364 double m0xm1 = m0.crossCheck(m1); | 402 double m0xm1 = m0.crossCheck(m1); |
| 365 if (s0xt0 > 0 && m0xm1 > 0) { | 403 if (s0xt0 > 0 && m0xm1 > 0) { |
| 366 return 0; | 404 return 0; |
| 367 } | 405 } |
| 368 if (s0xt0 < 0 && m0xm1 < 0) { | 406 if (s0xt0 < 0 && m0xm1 < 0) { |
| 369 return 1; | 407 return 1; |
| 370 } | 408 } |
| 371 if (tangentsDiverge(rh, s0xt0)) { | 409 if (tangentsDiverge(rh, s0xt0)) { |
| 372 return s0xt0 < 0; | 410 return s0xt0 < 0; |
| 373 } | 411 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 387 } | 425 } |
| 388 SkDVector v; | 426 SkDVector v; |
| 389 v.set(pts[idx2] - pts[idx1]); | 427 v.set(pts[idx2] - pts[idx1]); |
| 390 double lenSq = v.lengthSquared(); | 428 double lenSq = v.lengthSquared(); |
| 391 longest = SkTMax(longest, lenSq); | 429 longest = SkTMax(longest, lenSq); |
| 392 } | 430 } |
| 393 } | 431 } |
| 394 return sqrt(longest) / dist; | 432 return sqrt(longest) / dist; |
| 395 } | 433 } |
| 396 | 434 |
| 397 bool SkOpAngle::endsIntersect(const SkOpAngle& rh) const { | 435 bool SkOpAngle::endsIntersect(SkOpAngle* rh) { |
| 398 SkPath::Verb lVerb = fSegment->verb(); | 436 SkPath::Verb lVerb = this->segment()->verb(); |
| 399 SkPath::Verb rVerb = rh.fSegment->verb(); | 437 SkPath::Verb rVerb = rh->segment()->verb(); |
| 400 int lPts = SkPathOpsVerbToPoints(lVerb); | 438 int lPts = SkPathOpsVerbToPoints(lVerb); |
| 401 int rPts = SkPathOpsVerbToPoints(rVerb); | 439 int rPts = SkPathOpsVerbToPoints(rVerb); |
| 402 SkDLine rays[] = {{{fCurvePart[0], rh.fCurvePart[rPts]}}, | 440 SkDLine rays[] = {{{this->fCurvePart[0], rh->fCurvePart[rPts]}}, |
| 403 {{fCurvePart[0], fCurvePart[lPts]}}}; | 441 {{this->fCurvePart[0], this->fCurvePart[lPts]}}}; |
| 404 if (rays[0][1] == rays[1][1]) { | 442 if (rays[0][1] == rays[1][1]) { |
| 405 return checkParallel(rh); | 443 return checkParallel(rh); |
| 406 } | 444 } |
| 407 double smallTs[2] = {-1, -1}; | 445 double smallTs[2] = {-1, -1}; |
| 408 bool limited[2] = {false, false}; | 446 bool limited[2] = {false, false}; |
| 409 for (int index = 0; index < 2; ++index) { | 447 for (int index = 0; index < 2; ++index) { |
| 410 const SkOpSegment& segment = index ? *rh.fSegment : *fSegment; | |
| 411 SkIntersections i; | |
| 412 int cPts = index ? rPts : lPts; | 448 int cPts = index ? rPts : lPts; |
| 413 (*CurveIntersectRay[cPts])(segment.pts(), rays[index], &i); | |
| 414 // if the curve is a line, then the line and the ray intersect only at t
heir crossing | 449 // if the curve is a line, then the line and the ray intersect only at t
heir crossing |
| 415 if (cPts == 1) { // line | 450 if (cPts == 1) { // line |
| 416 continue; | 451 continue; |
| 417 } | 452 } |
| 418 // SkASSERT(i.used() >= 1); | 453 const SkOpSegment& segment = index ? *rh->segment() : *this->segment(); |
| 419 // if (i.used() <= 1) { | 454 SkIntersections i; |
| 420 // continue; | 455 (*CurveIntersectRay[cPts])(segment.pts(), rays[index], &i); |
| 421 // } | 456 double tStart = index ? rh->fStart->t() : this->fStart->t(); |
| 422 double tStart = segment.t(index ? rh.fStart : fStart); | 457 double tEnd = index ? rh->fComputedEnd->t() : this->fComputedEnd->t(); |
| 423 double tEnd = segment.t(index ? rh.fComputedEnd : fComputedEnd); | 458 bool testAscends = tStart < (index ? rh->fComputedEnd->t() : this->fComp
utedEnd->t()); |
| 424 bool testAscends = index ? rh.fStart < rh.fComputedEnd : fStart < fCompu
tedEnd; | |
| 425 double t = testAscends ? 0 : 1; | 459 double t = testAscends ? 0 : 1; |
| 426 for (int idx2 = 0; idx2 < i.used(); ++idx2) { | 460 for (int idx2 = 0; idx2 < i.used(); ++idx2) { |
| 427 double testT = i[0][idx2]; | 461 double testT = i[0][idx2]; |
| 428 if (!approximately_between_orderable(tStart, testT, tEnd)) { | 462 if (!approximately_between_orderable(tStart, testT, tEnd)) { |
| 429 continue; | 463 continue; |
| 430 } | 464 } |
| 431 if (approximately_equal_orderable(tStart, testT)) { | 465 if (approximately_equal_orderable(tStart, testT)) { |
| 432 continue; | 466 continue; |
| 433 } | 467 } |
| 434 smallTs[index] = t = testAscends ? SkTMax(t, testT) : SkTMin(t, test
T); | 468 smallTs[index] = t = testAscends ? SkTMax(t, testT) : SkTMin(t, test
T); |
| 435 limited[index] = approximately_equal_orderable(t, tEnd); | 469 limited[index] = approximately_equal_orderable(t, tEnd); |
| 436 } | 470 } |
| 437 } | 471 } |
| 438 #if 0 | |
| 439 if (smallTs[0] < 0 && smallTs[1] < 0) { // if neither ray intersects, do en
dpoint sort | |
| 440 double m0xm1 = 0; | |
| 441 if (lVerb == SkPath::kLine_Verb) { | |
| 442 SkASSERT(rVerb != SkPath::kLine_Verb); | |
| 443 SkDVector m0 = rays[1][1] - fCurvePart[0]; | |
| 444 SkDPoint endPt; | |
| 445 endPt.set(rh.fSegment->pts()[rh.fStart < rh.fEnd ? rPts : 0]); | |
| 446 SkDVector m1 = endPt - fCurvePart[0]; | |
| 447 m0xm1 = m0.crossCheck(m1); | |
| 448 } | |
| 449 if (rVerb == SkPath::kLine_Verb) { | |
| 450 SkDPoint endPt; | |
| 451 endPt.set(fSegment->pts()[fStart < fEnd ? lPts : 0]); | |
| 452 SkDVector m0 = endPt - fCurvePart[0]; | |
| 453 SkDVector m1 = rays[0][1] - fCurvePart[0]; | |
| 454 m0xm1 = m0.crossCheck(m1); | |
| 455 } | |
| 456 if (m0xm1 != 0) { | |
| 457 return m0xm1 < 0; | |
| 458 } | |
| 459 } | |
| 460 #endif | |
| 461 bool sRayLonger = false; | 472 bool sRayLonger = false; |
| 462 SkDVector sCept = {0, 0}; | 473 SkDVector sCept = {0, 0}; |
| 463 double sCeptT = -1; | 474 double sCeptT = -1; |
| 464 int sIndex = -1; | 475 int sIndex = -1; |
| 465 bool useIntersect = false; | 476 bool useIntersect = false; |
| 466 for (int index = 0; index < 2; ++index) { | 477 for (int index = 0; index < 2; ++index) { |
| 467 if (smallTs[index] < 0) { | 478 if (smallTs[index] < 0) { |
| 468 continue; | 479 continue; |
| 469 } | 480 } |
| 470 const SkOpSegment& segment = index ? *rh.fSegment : *fSegment; | 481 const SkOpSegment& segment = index ? *rh->segment() : *this->segment(); |
| 471 const SkDPoint& dPt = segment.dPtAtT(smallTs[index]); | 482 const SkDPoint& dPt = segment.dPtAtT(smallTs[index]); |
| 472 SkDVector cept = dPt - rays[index][0]; | 483 SkDVector cept = dPt - rays[index][0]; |
| 473 // If this point is on the curve, it should have been detected earlier b
y ordinary | 484 // If this point is on the curve, it should have been detected earlier b
y ordinary |
| 474 // curve intersection. This may be hard to determine in general, but for
lines, | 485 // curve intersection. This may be hard to determine in general, but for
lines, |
| 475 // the point could be close to or equal to its end, but shouldn't be nea
r the start. | 486 // the point could be close to or equal to its end, but shouldn't be nea
r the start. |
| 476 if ((index ? lPts : rPts) == 1) { | 487 if ((index ? lPts : rPts) == 1) { |
| 477 SkDVector total = rays[index][1] - rays[index][0]; | 488 SkDVector total = rays[index][1] - rays[index][0]; |
| 478 if (cept.lengthSquared() * 2 < total.lengthSquared()) { | 489 if (cept.lengthSquared() * 2 < total.lengthSquared()) { |
| 479 continue; | 490 continue; |
| 480 } | 491 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 491 sRayLonger = rayLonger; | 502 sRayLonger = rayLonger; |
| 492 sCept = cept; | 503 sCept = cept; |
| 493 sCeptT = smallTs[index]; | 504 sCeptT = smallTs[index]; |
| 494 sIndex = index; | 505 sIndex = index; |
| 495 break; | 506 break; |
| 496 } | 507 } |
| 497 double delta = fabs(rayDist - endDist); | 508 double delta = fabs(rayDist - endDist); |
| 498 double minX, minY, maxX, maxY; | 509 double minX, minY, maxX, maxY; |
| 499 minX = minY = SK_ScalarInfinity; | 510 minX = minY = SK_ScalarInfinity; |
| 500 maxX = maxY = -SK_ScalarInfinity; | 511 maxX = maxY = -SK_ScalarInfinity; |
| 501 const SkDCubic& curve = index ? rh.fCurvePart : fCurvePart; | 512 const SkDCubic& curve = index ? rh->fCurvePart : this->fCurvePart; |
| 502 int ptCount = index ? rPts : lPts; | 513 int ptCount = index ? rPts : lPts; |
| 503 for (int idx2 = 0; idx2 <= ptCount; ++idx2) { | 514 for (int idx2 = 0; idx2 <= ptCount; ++idx2) { |
| 504 minX = SkTMin(minX, curve[idx2].fX); | 515 minX = SkTMin(minX, curve[idx2].fX); |
| 505 minY = SkTMin(minY, curve[idx2].fY); | 516 minY = SkTMin(minY, curve[idx2].fY); |
| 506 maxX = SkTMax(maxX, curve[idx2].fX); | 517 maxX = SkTMax(maxX, curve[idx2].fX); |
| 507 maxY = SkTMax(maxY, curve[idx2].fY); | 518 maxY = SkTMax(maxY, curve[idx2].fY); |
| 508 } | 519 } |
| 509 double maxWidth = SkTMax(maxX - minX, maxY - minY); | 520 double maxWidth = SkTMax(maxX - minX, maxY - minY); |
| 510 delta /= maxWidth; | 521 delta /= maxWidth; |
| 511 if (delta > 1e-4 && (useIntersect ^= true)) { // FIXME: move this magic
number | 522 if (delta > 1e-3 && (useIntersect ^= true)) { // FIXME: move this magic
number |
| 512 sRayLonger = rayLonger; | 523 sRayLonger = rayLonger; |
| 513 sCept = cept; | 524 sCept = cept; |
| 514 sCeptT = smallTs[index]; | 525 sCeptT = smallTs[index]; |
| 515 sIndex = index; | 526 sIndex = index; |
| 516 } | 527 } |
| 517 } | 528 } |
| 518 if (useIntersect) { | 529 if (useIntersect) { |
| 519 const SkDCubic& curve = sIndex ? rh.fCurvePart : fCurvePart; | 530 const SkDCubic& curve = sIndex ? rh->fCurvePart : this->fCurvePart; |
| 520 const SkOpSegment& segment = sIndex ? *rh.fSegment : *fSegment; | 531 const SkOpSegment& segment = sIndex ? *rh->segment() : *this->segment(); |
| 521 double tStart = segment.t(sIndex ? rh.fStart : fStart); | 532 double tStart = sIndex ? rh->fStart->t() : fStart->t(); |
| 522 SkDVector mid = segment.dPtAtT(tStart + (sCeptT - tStart) / 2) - curve[0
]; | 533 SkDVector mid = segment.dPtAtT(tStart + (sCeptT - tStart) / 2) - curve[0
]; |
| 523 double septDir = mid.crossCheck(sCept); | 534 double septDir = mid.crossCheck(sCept); |
| 524 if (!septDir) { | 535 if (!septDir) { |
| 525 return checkParallel(rh); | 536 return checkParallel(rh); |
| 526 } | 537 } |
| 527 return sRayLonger ^ (sIndex == 0) ^ (septDir < 0); | 538 return sRayLonger ^ (sIndex == 0) ^ (septDir < 0); |
| 528 } else { | 539 } else { |
| 529 return checkParallel(rh); | 540 return checkParallel(rh); |
| 530 } | 541 } |
| 531 } | 542 } |
| 532 | 543 |
| 544 bool SkOpAngle::endToSide(const SkOpAngle* rh, bool* inside) const { |
| 545 const SkOpSegment* segment = this->segment(); |
| 546 SkPath::Verb verb = segment->verb(); |
| 547 int pts = SkPathOpsVerbToPoints(verb); |
| 548 SkDLine rayEnd; |
| 549 rayEnd[0].set(this->fEnd->pt()); |
| 550 rayEnd[1] = rayEnd[0]; |
| 551 SkDVector slopeAtEnd = (*CurveDSlopeAtT[pts])(segment->pts(), this->fEnd->t(
)); |
| 552 rayEnd[1].fX += slopeAtEnd.fY; |
| 553 rayEnd[1].fY -= slopeAtEnd.fX; |
| 554 SkIntersections iEnd; |
| 555 const SkOpSegment* oppSegment = rh->segment(); |
| 556 SkPath::Verb oppVerb = oppSegment->verb(); |
| 557 int oppPts = SkPathOpsVerbToPoints(oppVerb); |
| 558 (*CurveIntersectRay[oppPts])(oppSegment->pts(), rayEnd, &iEnd); |
| 559 double endDist; |
| 560 int closestEnd = iEnd.closestTo(rh->fStart->t(), rh->fEnd->t(), rayEnd[0], &
endDist); |
| 561 if (closestEnd < 0) { |
| 562 return false; |
| 563 } |
| 564 if (!endDist) { |
| 565 return false; |
| 566 } |
| 567 SkDPoint start; |
| 568 start.set(this->fStart->pt()); |
| 569 // OPTIMIZATION: multiple times in the code we find the max scalar |
| 570 double minX, minY, maxX, maxY; |
| 571 minX = minY = SK_ScalarInfinity; |
| 572 maxX = maxY = -SK_ScalarInfinity; |
| 573 const SkDCubic& curve = rh->fCurvePart; |
| 574 for (int idx2 = 0; idx2 <= oppPts; ++idx2) { |
| 575 minX = SkTMin(minX, curve[idx2].fX); |
| 576 minY = SkTMin(minY, curve[idx2].fY); |
| 577 maxX = SkTMax(maxX, curve[idx2].fX); |
| 578 maxY = SkTMax(maxY, curve[idx2].fY); |
| 579 } |
| 580 double maxWidth = SkTMax(maxX - minX, maxY - minY); |
| 581 endDist /= maxWidth; |
| 582 if (endDist < 5e-11) { // empirically found |
| 583 return false; |
| 584 } |
| 585 const SkDPoint* endPt = &rayEnd[0]; |
| 586 SkDPoint oppPt = iEnd.pt(closestEnd); |
| 587 SkDVector vLeft = *endPt - start; |
| 588 SkDVector vRight = oppPt - start; |
| 589 double dir = vLeft.crossCheck(vRight); |
| 590 if (!dir) { |
| 591 return false; |
| 592 } |
| 593 *inside = dir < 0; |
| 594 return true; |
| 595 } |
| 596 |
| 533 // Most of the time, the first one can be found trivially by detecting the small
est sector value. | 597 // Most of the time, the first one can be found trivially by detecting the small
est sector value. |
| 534 // If all angles have the same sector value, actual sorting is required. | 598 // If all angles have the same sector value, actual sorting is required. |
| 535 const SkOpAngle* SkOpAngle::findFirst() const { | 599 SkOpAngle* SkOpAngle::findFirst() { |
| 536 const SkOpAngle* best = this; | 600 SkOpAngle* best = this; |
| 537 int bestStart = SkTMin(fSectorStart, fSectorEnd); | 601 int bestStart = SkTMin(fSectorStart, fSectorEnd); |
| 538 const SkOpAngle* angle = this; | 602 SkOpAngle* angle = this; |
| 539 while ((angle = angle->fNext) != this) { | 603 while ((angle = angle->fNext) != this) { |
| 540 int angleEnd = SkTMax(angle->fSectorStart, angle->fSectorEnd); | 604 int angleEnd = SkTMax(angle->fSectorStart, angle->fSectorEnd); |
| 541 if (angleEnd < bestStart) { | 605 if (angleEnd < bestStart) { |
| 542 return angle; // we wrapped around | 606 return angle; // we wrapped around |
| 543 } | 607 } |
| 544 int angleStart = SkTMin(angle->fSectorStart, angle->fSectorEnd); | 608 int angleStart = SkTMin(angle->fSectorStart, angle->fSectorEnd); |
| 545 if (bestStart > angleStart) { | 609 if (bestStart > angleStart) { |
| 546 best = angle; | 610 best = angle; |
| 547 bestStart = angleStart; | 611 bestStart = angleStart; |
| 548 } | 612 } |
| 549 } | 613 } |
| 550 // back up to the first possible angle | 614 // back up to the first possible angle |
| 551 const SkOpAngle* firstBest = best; | 615 SkOpAngle* firstBest = best; |
| 552 angle = best; | 616 angle = best; |
| 553 int bestEnd = SkTMax(best->fSectorStart, best->fSectorEnd); | 617 int bestEnd = SkTMax(best->fSectorStart, best->fSectorEnd); |
| 554 while ((angle = angle->previous()) != firstBest) { | 618 while ((angle = angle->previous()) != firstBest) { |
| 555 if (angle->fStop) { | 619 if (angle->fStop) { |
| 556 break; | 620 break; |
| 557 } | 621 } |
| 558 int angleStart = SkTMin(angle->fSectorStart, angle->fSectorEnd); | 622 int angleStart = SkTMin(angle->fSectorStart, angle->fSectorEnd); |
| 559 // angles that are smaller by one aren't necessary better, since the lar
ger may be a line | 623 // angles that are smaller by one aren't necessary better, since the lar
ger may be a line |
| 560 // and the smaller may be a curve that curls to the other side of the li
ne. | 624 // and the smaller may be a curve that curls to the other side of the li
ne. |
| 561 if (bestEnd + 1 < angleStart) { | 625 if (bestEnd + 1 < angleStart) { |
| 562 return best; | 626 return best; |
| 563 } | 627 } |
| 564 best = angle; | 628 best = angle; |
| 565 bestEnd = SkTMax(angle->fSectorStart, angle->fSectorEnd); | 629 bestEnd = SkTMax(angle->fSectorStart, angle->fSectorEnd); |
| 566 } | 630 } |
| 567 // in the case where all angles are nearly in the same sector, check the ord
er to find the best | 631 // in the case where all angles are nearly in the same sector, check the ord
er to find the best |
| 568 firstBest = best; | 632 firstBest = best; |
| 569 angle = best; | 633 angle = best; |
| 570 do { | 634 do { |
| 571 angle = angle->fNext; | 635 angle = angle->fNext; |
| 572 if (angle->fStop) { | 636 if (angle->fStop) { |
| 573 return firstBest; | 637 return firstBest; |
| 574 } | 638 } |
| 575 bool orderable = best->orderable(*angle); // note: may return an unorde
rable angle | 639 bool orderable = best->orderable(angle); // note: may return an unorder
able angle |
| 576 if (orderable == 0) { | 640 if (orderable == 0) { |
| 577 return angle; | 641 return angle; |
| 578 } | 642 } |
| 579 best = angle; | 643 best = angle; |
| 580 } while (angle != firstBest); | 644 } while (angle != firstBest); |
| 581 // if the angles are equally ordered, fall back on the initial tangent | 645 // if the angles are equally ordered, fall back on the initial tangent |
| 582 bool foundBelow = false; | 646 bool foundBelow = false; |
| 583 while ((angle = angle->fNext)) { | 647 while ((angle = angle->fNext)) { |
| 584 SkDVector scratch[2]; | 648 SkDVector scratch[2]; |
| 585 const SkDVector* sweep; | 649 const SkDVector* sweep; |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 632 // x<0 x==0 x>0 x<0 x==0 x>0 x<0 x==0 x>0 | 696 // x<0 x==0 x>0 x<0 x==0 x>0 x<0 x==0 x>0 |
| 633 {{ 4, 3, 2}, { 7, -1, 15}, {10, 11, 12}}, // abs(x) < abs(y) | 697 {{ 4, 3, 2}, { 7, -1, 15}, {10, 11, 12}}, // abs(x) < abs(y) |
| 634 {{ 5, -1, 1}, {-1, -1, -1}, { 9, -1, 13}}, // abs(x) == abs(y) | 698 {{ 5, -1, 1}, {-1, -1, -1}, { 9, -1, 13}}, // abs(x) == abs(y) |
| 635 {{ 6, 3, 0}, { 7, -1, 15}, { 8, 11, 14}}, // abs(x) > abs(y) | 699 {{ 6, 3, 0}, { 7, -1, 15}, { 8, 11, 14}}, // abs(x) > abs(y) |
| 636 }; | 700 }; |
| 637 int sector = sedecimant[(xy >= 0) + (xy > 0)][(y >= 0) + (y > 0)][(x >= 0) +
(x > 0)] * 2 + 1; | 701 int sector = sedecimant[(xy >= 0) + (xy > 0)][(y >= 0) + (y > 0)][(x >= 0) +
(x > 0)] * 2 + 1; |
| 638 // SkASSERT(SkPath::kLine_Verb == verb || sector >= 0); | 702 // SkASSERT(SkPath::kLine_Verb == verb || sector >= 0); |
| 639 return sector; | 703 return sector; |
| 640 } | 704 } |
| 641 | 705 |
| 706 SkOpGlobalState* SkOpAngle::globalState() const { |
| 707 return this->segment()->globalState(); |
| 708 } |
| 709 |
| 710 |
| 642 // OPTIMIZE: if this loops to only one other angle, after first compare fails, i
nsert on other side | 711 // OPTIMIZE: if this loops to only one other angle, after first compare fails, i
nsert on other side |
| 643 // OPTIMIZE: return where insertion succeeded. Then, start next insertion on opp
osite side | 712 // OPTIMIZE: return where insertion succeeded. Then, start next insertion on opp
osite side |
| 644 void SkOpAngle::insert(SkOpAngle* angle) { | 713 void SkOpAngle::insert(SkOpAngle* angle) { |
| 645 if (angle->fNext) { | 714 if (angle->fNext) { |
| 646 if (loopCount() >= angle->loopCount()) { | 715 if (loopCount() >= angle->loopCount()) { |
| 647 if (!merge(angle)) { | 716 if (!merge(angle)) { |
| 648 return; | 717 return; |
| 649 } | 718 } |
| 650 } else if (fNext) { | 719 } else if (fNext) { |
| 651 if (!angle->merge(this)) { | 720 if (!angle->merge(this)) { |
| 652 return; | 721 return; |
| 653 } | 722 } |
| 654 } else { | 723 } else { |
| 655 angle->insert(this); | 724 angle->insert(this); |
| 656 } | 725 } |
| 657 return; | 726 return; |
| 658 } | 727 } |
| 659 bool singleton = NULL == fNext; | 728 bool singleton = NULL == fNext; |
| 660 if (singleton) { | 729 if (singleton) { |
| 661 fNext = this; | 730 fNext = this; |
| 662 } | 731 } |
| 663 SkOpAngle* next = fNext; | 732 SkOpAngle* next = fNext; |
| 664 if (next->fNext == this) { | 733 if (next->fNext == this) { |
| 665 if (angle->overlap(*this)) { // angles are essentially coincident | |
| 666 return; | |
| 667 } | |
| 668 if (singleton || angle->after(this)) { | 734 if (singleton || angle->after(this)) { |
| 669 this->fNext = angle; | 735 this->fNext = angle; |
| 670 angle->fNext = next; | 736 angle->fNext = next; |
| 671 } else { | 737 } else { |
| 672 next->fNext = angle; | 738 next->fNext = angle; |
| 673 angle->fNext = this; | 739 angle->fNext = this; |
| 674 } | 740 } |
| 675 debugValidateNext(); | 741 debugValidateNext(); |
| 676 return; | 742 return; |
| 677 } | 743 } |
| 678 SkOpAngle* last = this; | 744 SkOpAngle* last = this; |
| 679 do { | 745 do { |
| 680 SkASSERT(last->fNext == next); | 746 SkASSERT(last->fNext == next); |
| 681 if (angle->overlap(*last) || angle->overlap(*next)) { | |
| 682 return; | |
| 683 } | |
| 684 if (angle->after(last)) { | 747 if (angle->after(last)) { |
| 685 last->fNext = angle; | 748 last->fNext = angle; |
| 686 angle->fNext = next; | 749 angle->fNext = next; |
| 687 debugValidateNext(); | 750 debugValidateNext(); |
| 688 return; | 751 return; |
| 689 } | 752 } |
| 690 last = next; | 753 last = next; |
| 691 next = next->fNext; | 754 next = next->fNext; |
| 692 if (last == this && next->fUnorderable) { | 755 if (last == this) { |
| 693 fUnorderable = true; | 756 if (next->fUnorderable) { |
| 757 fUnorderable = true; |
| 758 } else { |
| 759 globalState()->setAngleCoincidence(); |
| 760 this->fNext = angle; |
| 761 angle->fNext = next; |
| 762 angle->fCheckCoincidence = true; |
| 763 } |
| 694 return; | 764 return; |
| 695 } | 765 } |
| 696 SkASSERT(last != this); | |
| 697 } while (true); | 766 } while (true); |
| 698 } | 767 } |
| 699 | 768 |
| 700 bool SkOpAngle::isHorizontal() const { | 769 SkOpSpanBase* SkOpAngle::lastMarked() const { |
| 701 return !fIsCurve && fSweep[0].fY == 0; | |
| 702 } | |
| 703 | |
| 704 SkOpSpan* SkOpAngle::lastMarked() const { | |
| 705 if (fLastMarked) { | 770 if (fLastMarked) { |
| 706 if (fLastMarked->fChased) { | 771 if (fLastMarked->chased()) { |
| 707 return NULL; | 772 return NULL; |
| 708 } | 773 } |
| 709 fLastMarked->fChased = true; | 774 fLastMarked->setChased(true); |
| 710 } | 775 } |
| 711 return fLastMarked; | 776 return fLastMarked; |
| 712 } | 777 } |
| 713 | 778 |
| 714 bool SkOpAngle::loopContains(const SkOpAngle& test) const { | 779 bool SkOpAngle::loopContains(const SkOpAngle* angle) const { |
| 715 if (!fNext) { | 780 if (!fNext) { |
| 716 return false; | 781 return false; |
| 717 } | 782 } |
| 718 const SkOpAngle* first = this; | 783 const SkOpAngle* first = this; |
| 719 const SkOpAngle* loop = this; | 784 const SkOpAngle* loop = this; |
| 720 const SkOpSegment* tSegment = test.fSegment; | 785 const SkOpSegment* tSegment = angle->fStart->segment(); |
| 721 double tStart = tSegment->span(test.fStart).fT; | 786 double tStart = angle->fStart->t(); |
| 722 double tEnd = tSegment->span(test.fEnd).fT; | 787 double tEnd = angle->fEnd->t(); |
| 723 do { | 788 do { |
| 724 const SkOpSegment* lSegment = loop->fSegment; | 789 const SkOpSegment* lSegment = loop->fStart->segment(); |
| 725 // FIXME : use precisely_equal ? or compare points exactly ? | |
| 726 if (lSegment != tSegment) { | 790 if (lSegment != tSegment) { |
| 727 continue; | 791 continue; |
| 728 } | 792 } |
| 729 double lStart = lSegment->span(loop->fStart).fT; | 793 double lStart = loop->fStart->t(); |
| 730 if (lStart != tEnd) { | 794 if (lStart != tEnd) { |
| 731 continue; | 795 continue; |
| 732 } | 796 } |
| 733 double lEnd = lSegment->span(loop->fEnd).fT; | 797 double lEnd = loop->fEnd->t(); |
| 734 if (lEnd == tStart) { | 798 if (lEnd == tStart) { |
| 735 return true; | 799 return true; |
| 736 } | 800 } |
| 737 } while ((loop = loop->fNext) != first); | 801 } while ((loop = loop->fNext) != first); |
| 738 return false; | 802 return false; |
| 739 } | 803 } |
| 740 | 804 |
| 741 int SkOpAngle::loopCount() const { | 805 int SkOpAngle::loopCount() const { |
| 742 int count = 0; | 806 int count = 0; |
| 743 const SkOpAngle* first = this; | 807 const SkOpAngle* first = this; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 775 } | 839 } |
| 776 working = working->fNext; | 840 working = working->fNext; |
| 777 } while (working != angle); | 841 } while (working != angle); |
| 778 do { | 842 do { |
| 779 SkOpAngle* next = working->fNext; | 843 SkOpAngle* next = working->fNext; |
| 780 working->fNext = NULL; | 844 working->fNext = NULL; |
| 781 insert(working); | 845 insert(working); |
| 782 working = next; | 846 working = next; |
| 783 } while (working != angle); | 847 } while (working != angle); |
| 784 // it's likely that a pair of the angles are unorderable | 848 // it's likely that a pair of the angles are unorderable |
| 785 #if 0 && DEBUG_ANGLE | |
| 786 SkOpAngle* last = angle; | |
| 787 working = angle->fNext; | |
| 788 do { | |
| 789 SkASSERT(last->fNext == working); | |
| 790 last->fNext = working->fNext; | |
| 791 SkASSERT(working->after(last)); | |
| 792 last->fNext = working; | |
| 793 last = working; | |
| 794 working = working->fNext; | |
| 795 } while (last != angle); | |
| 796 #endif | |
| 797 debugValidateNext(); | 849 debugValidateNext(); |
| 798 return true; | 850 return true; |
| 799 } | 851 } |
| 800 | 852 |
| 801 double SkOpAngle::midT() const { | 853 double SkOpAngle::midT() const { |
| 802 return (fSegment->t(fStart) + fSegment->t(fEnd)) / 2; | 854 return (fStart->t() + fEnd->t()) / 2; |
| 803 } | 855 } |
| 804 | 856 |
| 805 bool SkOpAngle::oppositePlanes(const SkOpAngle& rh) const { | 857 bool SkOpAngle::midToSide(const SkOpAngle* rh, bool* inside) const { |
| 806 int startSpan = abs(rh.fSectorStart - fSectorStart); | 858 const SkOpSegment* segment = this->segment(); |
| 859 SkPath::Verb verb = segment->verb(); |
| 860 int pts = SkPathOpsVerbToPoints(verb); |
| 861 const SkPoint& startPt = this->fStart->pt(); |
| 862 const SkPoint& endPt = this->fEnd->pt(); |
| 863 SkDPoint dStartPt; |
| 864 dStartPt.set(startPt); |
| 865 SkDLine rayMid; |
| 866 rayMid[0].fX = (startPt.fX + endPt.fX) / 2; |
| 867 rayMid[0].fY = (startPt.fY + endPt.fY) / 2; |
| 868 rayMid[1].fX = rayMid[0].fX + (endPt.fY - startPt.fY); |
| 869 rayMid[1].fY = rayMid[0].fY - (endPt.fX - startPt.fX); |
| 870 SkIntersections iMid; |
| 871 (*CurveIntersectRay[pts])(segment->pts(), rayMid, &iMid); |
| 872 int iOutside = iMid.mostOutside(this->fStart->t(), this->fEnd->t(), dStartPt
); |
| 873 if (iOutside < 0) { |
| 874 return false; |
| 875 } |
| 876 const SkOpSegment* oppSegment = rh->segment(); |
| 877 SkPath::Verb oppVerb = oppSegment->verb(); |
| 878 int oppPts = SkPathOpsVerbToPoints(oppVerb); |
| 879 SkIntersections oppMid; |
| 880 (*CurveIntersectRay[oppPts])(oppSegment->pts(), rayMid, &oppMid); |
| 881 int oppOutside = oppMid.mostOutside(rh->fStart->t(), rh->fEnd->t(), dStartPt
); |
| 882 if (oppOutside < 0) { |
| 883 return false; |
| 884 } |
| 885 SkDVector iSide = iMid.pt(iOutside) - dStartPt; |
| 886 SkDVector oppSide = oppMid.pt(oppOutside) - dStartPt; |
| 887 double dir = iSide.crossCheck(oppSide); |
| 888 if (!dir) { |
| 889 return false; |
| 890 } |
| 891 *inside = dir < 0; |
| 892 return true; |
| 893 } |
| 894 |
| 895 bool SkOpAngle::oppositePlanes(const SkOpAngle* rh) const { |
| 896 int startSpan = abs(rh->fSectorStart - fSectorStart); |
| 807 return startSpan >= 8; | 897 return startSpan >= 8; |
| 808 } | 898 } |
| 809 | 899 |
| 810 bool SkOpAngle::orderable(const SkOpAngle& rh) const { | 900 bool SkOpAngle::orderable(SkOpAngle* rh) { |
| 811 int result; | 901 int result; |
| 812 if (!fIsCurve) { | 902 if (!fIsCurve) { |
| 813 if (!rh.fIsCurve) { | 903 if (!rh->fIsCurve) { |
| 814 double leftX = fTangentHalf.dx(); | 904 double leftX = fTangentHalf.dx(); |
| 815 double leftY = fTangentHalf.dy(); | 905 double leftY = fTangentHalf.dy(); |
| 816 double rightX = rh.fTangentHalf.dx(); | 906 double rightX = rh->fTangentHalf.dx(); |
| 817 double rightY = rh.fTangentHalf.dy(); | 907 double rightY = rh->fTangentHalf.dy(); |
| 818 double x_ry = leftX * rightY; | 908 double x_ry = leftX * rightY; |
| 819 double rx_y = rightX * leftY; | 909 double rx_y = rightX * leftY; |
| 820 if (x_ry == rx_y) { | 910 if (x_ry == rx_y) { |
| 821 if (leftX * rightX < 0 || leftY * rightY < 0) { | 911 if (leftX * rightX < 0 || leftY * rightY < 0) { |
| 822 return true; // exactly 180 degrees apart | 912 return true; // exactly 180 degrees apart |
| 823 } | 913 } |
| 824 goto unorderable; | 914 goto unorderable; |
| 825 } | 915 } |
| 826 SkASSERT(x_ry != rx_y); // indicates an undetected coincidence -- wo
rth finding earlier | 916 SkASSERT(x_ry != rx_y); // indicates an undetected coincidence -- wo
rth finding earlier |
| 827 return x_ry < rx_y; | 917 return x_ry < rx_y; |
| 828 } | 918 } |
| 829 if ((result = allOnOneSide(rh)) >= 0) { | 919 if ((result = allOnOneSide(rh)) >= 0) { |
| 830 return result; | 920 return result; |
| 831 } | 921 } |
| 832 if (fUnorderable || approximately_zero(rh.fSide)) { | 922 if (fUnorderable || approximately_zero(rh->fSide)) { |
| 833 goto unorderable; | 923 goto unorderable; |
| 834 } | 924 } |
| 835 } else if (!rh.fIsCurve) { | 925 } else if (!rh->fIsCurve) { |
| 836 if ((result = rh.allOnOneSide(*this)) >= 0) { | 926 if ((result = rh->allOnOneSide(this)) >= 0) { |
| 837 return !result; | 927 return !result; |
| 838 } | 928 } |
| 839 if (rh.fUnorderable || approximately_zero(fSide)) { | 929 if (rh->fUnorderable || approximately_zero(fSide)) { |
| 840 goto unorderable; | 930 goto unorderable; |
| 841 } | 931 } |
| 842 } | 932 } |
| 843 if ((result = convexHullOverlaps(rh)) >= 0) { | 933 if ((result = convexHullOverlaps(rh)) >= 0) { |
| 844 return result; | 934 return result; |
| 845 } | 935 } |
| 846 return endsIntersect(rh); | 936 return endsIntersect(rh); |
| 847 unorderable: | 937 unorderable: |
| 848 fUnorderable = true; | 938 fUnorderable = true; |
| 849 rh.fUnorderable = true; | 939 rh->fUnorderable = true; |
| 850 return true; | 940 return true; |
| 851 } | 941 } |
| 852 | 942 |
| 853 bool SkOpAngle::overlap(const SkOpAngle& other) const { | |
| 854 int min = SkTMin(fStart, fEnd); | |
| 855 const SkOpSpan& span = fSegment->span(min); | |
| 856 const SkOpSegment* oSeg = other.fSegment; | |
| 857 int oMin = SkTMin(other.fStart, other.fEnd); | |
| 858 const SkOpSpan& oSpan = oSeg->span(oMin); | |
| 859 if (!span.fSmall && !oSpan.fSmall) { | |
| 860 return false; | |
| 861 } | |
| 862 if (fSegment->span(fStart).fPt != oSeg->span(other.fStart).fPt) { | |
| 863 return false; | |
| 864 } | |
| 865 // see if small span is contained by opposite span | |
| 866 return span.fSmall ? oSeg->containsPt(fSegment->span(fEnd).fPt, other.fEnd,
other.fStart) | |
| 867 : fSegment->containsPt(oSeg->span(other.fEnd).fPt, fEnd, fStart); | |
| 868 } | |
| 869 | |
| 870 // OPTIMIZE: if this shows up in a profile, add a previous pointer | 943 // OPTIMIZE: if this shows up in a profile, add a previous pointer |
| 871 // as is, this should be rarely called | 944 // as is, this should be rarely called |
| 872 SkOpAngle* SkOpAngle::previous() const { | 945 SkOpAngle* SkOpAngle::previous() const { |
| 873 SkOpAngle* last = fNext; | 946 SkOpAngle* last = fNext; |
| 874 do { | 947 do { |
| 875 SkOpAngle* next = last->fNext; | 948 SkOpAngle* next = last->fNext; |
| 876 if (next == this) { | 949 if (next == this) { |
| 877 return last; | 950 return last; |
| 878 } | 951 } |
| 879 last = next; | 952 last = next; |
| 880 } while (true); | 953 } while (true); |
| 881 } | 954 } |
| 882 | 955 |
| 883 void SkOpAngle::set(const SkOpSegment* segment, int start, int end) { | 956 SkOpSegment* SkOpAngle::segment() const { |
| 884 fSegment = segment; | 957 return fStart->segment(); |
| 958 } |
| 959 |
| 960 void SkOpAngle::set(SkOpSpanBase* start, SkOpSpanBase* end) { |
| 885 fStart = start; | 961 fStart = start; |
| 886 fComputedEnd = fEnd = end; | 962 fComputedEnd = fEnd = end; |
| 963 SkASSERT(start != end); |
| 887 fNext = NULL; | 964 fNext = NULL; |
| 888 fComputeSector = fComputedSector = false; | 965 fComputeSector = fComputedSector = fCheckCoincidence = false; |
| 889 fStop = false; | 966 fStop = false; |
| 890 setSpans(); | 967 setSpans(); |
| 891 setSector(); | 968 setSector(); |
| 969 PATH_OPS_DEBUG_CODE(fID = start->globalState()->nextAngleID()); |
| 892 } | 970 } |
| 893 | 971 |
| 894 void SkOpAngle::setCurveHullSweep() { | 972 void SkOpAngle::setCurveHullSweep() { |
| 895 fUnorderedSweep = false; | 973 fUnorderedSweep = false; |
| 896 fSweep[0] = fCurvePart[1] - fCurvePart[0]; | 974 fSweep[0] = fCurvePart[1] - fCurvePart[0]; |
| 897 if (SkPath::kLine_Verb == fSegment->verb()) { | 975 const SkOpSegment* segment = fStart->segment(); |
| 976 if (SkPath::kLine_Verb == segment->verb()) { |
| 898 fSweep[1] = fSweep[0]; | 977 fSweep[1] = fSweep[0]; |
| 899 return; | 978 return; |
| 900 } | 979 } |
| 901 fSweep[1] = fCurvePart[2] - fCurvePart[0]; | 980 fSweep[1] = fCurvePart[2] - fCurvePart[0]; |
| 902 if (SkPath::kCubic_Verb != fSegment->verb()) { | 981 if (SkPath::kCubic_Verb != segment->verb()) { |
| 903 if (!fSweep[0].fX && !fSweep[0].fY) { | 982 if (!fSweep[0].fX && !fSweep[0].fY) { |
| 904 fSweep[0] = fSweep[1]; | 983 fSweep[0] = fSweep[1]; |
| 905 } | 984 } |
| 906 return; | 985 return; |
| 907 } | 986 } |
| 908 SkDVector thirdSweep = fCurvePart[3] - fCurvePart[0]; | 987 SkDVector thirdSweep = fCurvePart[3] - fCurvePart[0]; |
| 909 if (fSweep[0].fX == 0 && fSweep[0].fY == 0) { | 988 if (fSweep[0].fX == 0 && fSweep[0].fY == 0) { |
| 910 fSweep[0] = fSweep[1]; | 989 fSweep[0] = fSweep[1]; |
| 911 fSweep[1] = thirdSweep; | 990 fSweep[1] = thirdSweep; |
| 912 if (fSweep[0].fX == 0 && fSweep[0].fY == 0) { | 991 if (fSweep[0].fX == 0 && fSweep[0].fY == 0) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 926 // probably such wide sweeps should be artificially subdivided earlier so th
at never happens | 1005 // probably such wide sweeps should be artificially subdivided earlier so th
at never happens |
| 927 SkASSERT(s1x3 * s2x1 < 0 || s1x3 * s3x2 < 0); | 1006 SkASSERT(s1x3 * s2x1 < 0 || s1x3 * s3x2 < 0); |
| 928 if (s3x2 * s2x1 < 0) { | 1007 if (s3x2 * s2x1 < 0) { |
| 929 SkASSERT(s2x1 * s1x3 > 0); | 1008 SkASSERT(s2x1 * s1x3 > 0); |
| 930 fSweep[0] = fSweep[1]; | 1009 fSweep[0] = fSweep[1]; |
| 931 fUnorderedSweep = true; | 1010 fUnorderedSweep = true; |
| 932 } | 1011 } |
| 933 fSweep[1] = thirdSweep; | 1012 fSweep[1] = thirdSweep; |
| 934 } | 1013 } |
| 935 | 1014 |
| 936 void SkOpAngle::setSector() { | |
| 937 SkPath::Verb verb = fSegment->verb(); | |
| 938 if (SkPath::kLine_Verb != verb && small()) { | |
| 939 goto deferTilLater; | |
| 940 } | |
| 941 fSectorStart = findSector(verb, fSweep[0].fX, fSweep[0].fY); | |
| 942 if (fSectorStart < 0) { | |
| 943 goto deferTilLater; | |
| 944 } | |
| 945 if (!fIsCurve) { // if it's a line or line-like, note that both sectors are
the same | |
| 946 SkASSERT(fSectorStart >= 0); | |
| 947 fSectorEnd = fSectorStart; | |
| 948 fSectorMask = 1 << fSectorStart; | |
| 949 return; | |
| 950 } | |
| 951 SkASSERT(SkPath::kLine_Verb != verb); | |
| 952 fSectorEnd = findSector(verb, fSweep[1].fX, fSweep[1].fY); | |
| 953 if (fSectorEnd < 0) { | |
| 954 deferTilLater: | |
| 955 fSectorStart = fSectorEnd = -1; | |
| 956 fSectorMask = 0; | |
| 957 fComputeSector = true; // can't determine sector until segment length c
an be found | |
| 958 return; | |
| 959 } | |
| 960 if (fSectorEnd == fSectorStart) { | |
| 961 SkASSERT((fSectorStart & 3) != 3); // if the sector has no span, it can
't be an exact angle | |
| 962 fSectorMask = 1 << fSectorStart; | |
| 963 return; | |
| 964 } | |
| 965 bool crossesZero = checkCrossesZero(); | |
| 966 int start = SkTMin(fSectorStart, fSectorEnd); | |
| 967 bool curveBendsCCW = (fSectorStart == start) ^ crossesZero; | |
| 968 // bump the start and end of the sector span if they are on exact compass po
ints | |
| 969 if ((fSectorStart & 3) == 3) { | |
| 970 fSectorStart = (fSectorStart + (curveBendsCCW ? 1 : 31)) & 0x1f; | |
| 971 } | |
| 972 if ((fSectorEnd & 3) == 3) { | |
| 973 fSectorEnd = (fSectorEnd + (curveBendsCCW ? 31 : 1)) & 0x1f; | |
| 974 } | |
| 975 crossesZero = checkCrossesZero(); | |
| 976 start = SkTMin(fSectorStart, fSectorEnd); | |
| 977 int end = SkTMax(fSectorStart, fSectorEnd); | |
| 978 if (!crossesZero) { | |
| 979 fSectorMask = (unsigned) -1 >> (31 - end + start) << start; | |
| 980 } else { | |
| 981 fSectorMask = (unsigned) -1 >> (31 - start) | (-1 << end); | |
| 982 } | |
| 983 } | |
| 984 | |
| 985 void SkOpAngle::setSpans() { | 1015 void SkOpAngle::setSpans() { |
| 986 fUnorderable = fSegment->isTiny(this); | 1016 fUnorderable = false; |
| 987 fLastMarked = NULL; | 1017 fLastMarked = NULL; |
| 988 const SkPoint* pts = fSegment->pts(); | 1018 const SkOpSegment* segment = fStart->segment(); |
| 1019 const SkPoint* pts = segment->pts(); |
| 989 SkDEBUGCODE(fCurvePart[2].fX = fCurvePart[2].fY = fCurvePart[3].fX = fCurveP
art[3].fY | 1020 SkDEBUGCODE(fCurvePart[2].fX = fCurvePart[2].fY = fCurvePart[3].fX = fCurveP
art[3].fY |
| 990 = SK_ScalarNaN); | 1021 = SK_ScalarNaN); |
| 991 fSegment->subDivide(fStart, fEnd, &fCurvePart); | 1022 segment->subDivide(fStart, fEnd, &fCurvePart); |
| 992 setCurveHullSweep(); | 1023 setCurveHullSweep(); |
| 993 const SkPath::Verb verb = fSegment->verb(); | 1024 const SkPath::Verb verb = segment->verb(); |
| 994 if (verb != SkPath::kLine_Verb | 1025 if (verb != SkPath::kLine_Verb |
| 995 && !(fIsCurve = fSweep[0].crossCheck(fSweep[1]) != 0)) { | 1026 && !(fIsCurve = fSweep[0].crossCheck(fSweep[1]) != 0)) { |
| 996 SkDLine lineHalf; | 1027 SkDLine lineHalf; |
| 997 lineHalf[0].set(fCurvePart[0].asSkPoint()); | 1028 lineHalf[0].set(fCurvePart[0].asSkPoint()); |
| 998 lineHalf[1].set(fCurvePart[SkPathOpsVerbToPoints(verb)].asSkPoint()); | 1029 lineHalf[1].set(fCurvePart[SkPathOpsVerbToPoints(verb)].asSkPoint()); |
| 999 fTangentHalf.lineEndPoints(lineHalf); | 1030 fTangentHalf.lineEndPoints(lineHalf); |
| 1000 fSide = 0; | 1031 fSide = 0; |
| 1001 } | 1032 } |
| 1002 switch (verb) { | 1033 switch (verb) { |
| 1003 case SkPath::kLine_Verb: { | 1034 case SkPath::kLine_Verb: { |
| 1004 SkASSERT(fStart != fEnd); | 1035 SkASSERT(fStart != fEnd); |
| 1005 const SkPoint& cP1 = pts[fStart < fEnd]; | 1036 const SkPoint& cP1 = pts[fStart->t() < fEnd->t()]; |
| 1006 SkDLine lineHalf; | 1037 SkDLine lineHalf; |
| 1007 lineHalf[0].set(fSegment->span(fStart).fPt); | 1038 lineHalf[0].set(fStart->pt()); |
| 1008 lineHalf[1].set(cP1); | 1039 lineHalf[1].set(cP1); |
| 1009 fTangentHalf.lineEndPoints(lineHalf); | 1040 fTangentHalf.lineEndPoints(lineHalf); |
| 1010 fSide = 0; | 1041 fSide = 0; |
| 1011 fIsCurve = false; | 1042 fIsCurve = false; |
| 1012 } return; | 1043 } return; |
| 1013 case SkPath::kQuad_Verb: { | 1044 case SkPath::kQuad_Verb: { |
| 1014 SkLineParameters tangentPart; | 1045 SkLineParameters tangentPart; |
| 1015 SkDQuad& quad2 = *SkTCast<SkDQuad*>(&fCurvePart); | 1046 SkDQuad& quad2 = *SkTCast<SkDQuad*>(&fCurvePart); |
| 1016 (void) tangentPart.quadEndPoints(quad2); | 1047 (void) tangentPart.quadEndPoints(quad2); |
| 1017 fSide = -tangentPart.pointDistance(fCurvePart[2]); // not normalized --
compare sign only | 1048 fSide = -tangentPart.pointDistance(fCurvePart[2]); // not normalized --
compare sign only |
| 1018 } break; | 1049 } break; |
| 1019 case SkPath::kCubic_Verb: { | 1050 case SkPath::kCubic_Verb: { |
| 1020 SkLineParameters tangentPart; | 1051 SkLineParameters tangentPart; |
| 1021 (void) tangentPart.cubicPart(fCurvePart); | 1052 (void) tangentPart.cubicPart(fCurvePart); |
| 1022 fSide = -tangentPart.pointDistance(fCurvePart[3]); | 1053 fSide = -tangentPart.pointDistance(fCurvePart[3]); |
| 1023 double testTs[4]; | 1054 double testTs[4]; |
| 1024 // OPTIMIZATION: keep inflections precomputed with cubic segment? | 1055 // OPTIMIZATION: keep inflections precomputed with cubic segment? |
| 1025 int testCount = SkDCubic::FindInflections(pts, testTs); | 1056 int testCount = SkDCubic::FindInflections(pts, testTs); |
| 1026 double startT = fSegment->t(fStart); | 1057 double startT = fStart->t(); |
| 1027 double endT = fSegment->t(fEnd); | 1058 double endT = fEnd->t(); |
| 1028 double limitT = endT; | 1059 double limitT = endT; |
| 1029 int index; | 1060 int index; |
| 1030 for (index = 0; index < testCount; ++index) { | 1061 for (index = 0; index < testCount; ++index) { |
| 1031 if (!::between(startT, testTs[index], limitT)) { | 1062 if (!::between(startT, testTs[index], limitT)) { |
| 1032 testTs[index] = -1; | 1063 testTs[index] = -1; |
| 1033 } | 1064 } |
| 1034 } | 1065 } |
| 1035 testTs[testCount++] = startT; | 1066 testTs[testCount++] = startT; |
| 1036 testTs[testCount++] = endT; | 1067 testTs[testCount++] = endT; |
| 1037 SkTQSort<double>(testTs, &testTs[testCount - 1]); | 1068 SkTQSort<double>(testTs, &testTs[testCount - 1]); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1057 bestSide = testSide; | 1088 bestSide = testSide; |
| 1058 } | 1089 } |
| 1059 } | 1090 } |
| 1060 fSide = -bestSide; // compare sign only | 1091 fSide = -bestSide; // compare sign only |
| 1061 } break; | 1092 } break; |
| 1062 default: | 1093 default: |
| 1063 SkASSERT(0); | 1094 SkASSERT(0); |
| 1064 } | 1095 } |
| 1065 } | 1096 } |
| 1066 | 1097 |
| 1067 bool SkOpAngle::small() const { | 1098 void SkOpAngle::setSector() { |
| 1068 int min = SkMin32(fStart, fEnd); | 1099 const SkOpSegment* segment = fStart->segment(); |
| 1069 int max = SkMax32(fStart, fEnd); | 1100 SkPath::Verb verb = segment->verb(); |
| 1070 for (int index = min; index < max; ++index) { | 1101 fSectorStart = this->findSector(verb, fSweep[0].fX, fSweep[0].fY); |
| 1071 const SkOpSpan& mSpan = fSegment->span(index); | 1102 if (fSectorStart < 0) { |
| 1072 if (!mSpan.fSmall) { | 1103 goto deferTilLater; |
| 1073 return false; | |
| 1074 } | |
| 1075 } | 1104 } |
| 1076 return true; | 1105 if (!fIsCurve) { // if it's a line or line-like, note that both sectors are
the same |
| 1106 SkASSERT(fSectorStart >= 0); |
| 1107 fSectorEnd = fSectorStart; |
| 1108 fSectorMask = 1 << fSectorStart; |
| 1109 return; |
| 1110 } |
| 1111 SkASSERT(SkPath::kLine_Verb != verb); |
| 1112 fSectorEnd = this->findSector(verb, fSweep[1].fX, fSweep[1].fY); |
| 1113 if (fSectorEnd < 0) { |
| 1114 deferTilLater: |
| 1115 fSectorStart = fSectorEnd = -1; |
| 1116 fSectorMask = 0; |
| 1117 fComputeSector = true; // can't determine sector until segment length c
an be found |
| 1118 return; |
| 1119 } |
| 1120 if (fSectorEnd == fSectorStart |
| 1121 && (fSectorStart & 3) != 3) { // if the sector has no span, it can't
be an exact angle |
| 1122 fSectorMask = 1 << fSectorStart; |
| 1123 return; |
| 1124 } |
| 1125 bool crossesZero = this->checkCrossesZero(); |
| 1126 int start = SkTMin(fSectorStart, fSectorEnd); |
| 1127 bool curveBendsCCW = (fSectorStart == start) ^ crossesZero; |
| 1128 // bump the start and end of the sector span if they are on exact compass po
ints |
| 1129 if ((fSectorStart & 3) == 3) { |
| 1130 fSectorStart = (fSectorStart + (curveBendsCCW ? 1 : 31)) & 0x1f; |
| 1131 } |
| 1132 if ((fSectorEnd & 3) == 3) { |
| 1133 fSectorEnd = (fSectorEnd + (curveBendsCCW ? 31 : 1)) & 0x1f; |
| 1134 } |
| 1135 crossesZero = this->checkCrossesZero(); |
| 1136 start = SkTMin(fSectorStart, fSectorEnd); |
| 1137 int end = SkTMax(fSectorStart, fSectorEnd); |
| 1138 if (!crossesZero) { |
| 1139 fSectorMask = (unsigned) -1 >> (31 - end + start) << start; |
| 1140 } else { |
| 1141 fSectorMask = (unsigned) -1 >> (31 - start) | (-1 << end); |
| 1142 } |
| 1077 } | 1143 } |
| 1078 | 1144 |
| 1079 bool SkOpAngle::tangentsDiverge(const SkOpAngle& rh, double s0xt0) const { | 1145 int SkOpAngle::sign() const { |
| 1146 SkASSERT(fStart->t() != fEnd->t()); |
| 1147 return fStart->t() < fEnd->t() ? -1 : 1; |
| 1148 } |
| 1149 |
| 1150 SkOpSpan* SkOpAngle::starter() { |
| 1151 return fStart->starter(fEnd); |
| 1152 } |
| 1153 |
| 1154 bool SkOpAngle::tangentsDiverge(const SkOpAngle* rh, double s0xt0) const { |
| 1080 if (s0xt0 == 0) { | 1155 if (s0xt0 == 0) { |
| 1081 return false; | 1156 return false; |
| 1082 } | 1157 } |
| 1083 // if the ctrl tangents are not nearly parallel, use them | 1158 // if the ctrl tangents are not nearly parallel, use them |
| 1084 // solve for opposite direction displacement scale factor == m | 1159 // solve for opposite direction displacement scale factor == m |
| 1085 // initial dir = v1.cross(v2) == v2.x * v1.y - v2.y * v1.x | 1160 // initial dir = v1.cross(v2) == v2.x * v1.y - v2.y * v1.x |
| 1086 // displacement of q1[1] : dq1 = { -m * v1.y, m * v1.x } + q1[1] | 1161 // displacement of q1[1] : dq1 = { -m * v1.y, m * v1.x } + q1[1] |
| 1087 // straight angle when : v2.x * (dq1.y - q1[0].y) == v2.y * (dq1.x - q1[0].x
) | 1162 // straight angle when : v2.x * (dq1.y - q1[0].y) == v2.y * (dq1.x - q1[0].x
) |
| 1088 // v2.x * (m * v1.x + v1.y) == v2.y * (-m * v1.y + v1.
x) | 1163 // v2.x * (m * v1.x + v1.y) == v2.y * (-m * v1.y + v1.
x) |
| 1089 // - m * (v2.x * v1.x + v2.y * v1.y) == v2.x * v1.y - v2.y * v1.x | 1164 // - m * (v2.x * v1.x + v2.y * v1.y) == v2.x * v1.y - v2.y * v1.x |
| 1090 // m = (v2.y * v1.x - v2.x * v1.y) / (v2.x * v1.x + v2.y * v1.y) | 1165 // m = (v2.y * v1.x - v2.x * v1.y) / (v2.x * v1.x + v2.y * v1.y) |
| 1091 // m = v1.cross(v2) / v1.dot(v2) | 1166 // m = v1.cross(v2) / v1.dot(v2) |
| 1092 const SkDVector* sweep = fSweep; | 1167 const SkDVector* sweep = fSweep; |
| 1093 const SkDVector* tweep = rh.fSweep; | 1168 const SkDVector* tweep = rh->fSweep; |
| 1094 double s0dt0 = sweep[0].dot(tweep[0]); | 1169 double s0dt0 = sweep[0].dot(tweep[0]); |
| 1095 if (!s0dt0) { | 1170 if (!s0dt0) { |
| 1096 return true; | 1171 return true; |
| 1097 } | 1172 } |
| 1098 SkASSERT(s0dt0 != 0); | 1173 SkASSERT(s0dt0 != 0); |
| 1099 double m = s0xt0 / s0dt0; | 1174 double m = s0xt0 / s0dt0; |
| 1100 double sDist = sweep[0].length() * m; | 1175 double sDist = sweep[0].length() * m; |
| 1101 double tDist = tweep[0].length() * m; | 1176 double tDist = tweep[0].length() * m; |
| 1102 bool useS = fabs(sDist) < fabs(tDist); | 1177 bool useS = fabs(sDist) < fabs(tDist); |
| 1103 double mFactor = fabs(useS ? distEndRatio(sDist) : rh.distEndRatio(tDist)); | 1178 double mFactor = fabs(useS ? this->distEndRatio(sDist) : rh->distEndRatio(tD
ist)); |
| 1104 return mFactor < 5000; // empirically found limit | 1179 return mFactor < 5000; // empirically found limit |
| 1105 } | 1180 } |
| 1106 | |
| 1107 SkOpAngleSet::SkOpAngleSet() | |
| 1108 : fAngles(NULL) | |
| 1109 #if DEBUG_ANGLE | |
| 1110 , fCount(0) | |
| 1111 #endif | |
| 1112 { | |
| 1113 } | |
| 1114 | |
| 1115 SkOpAngleSet::~SkOpAngleSet() { | |
| 1116 SkDELETE(fAngles); | |
| 1117 } | |
| 1118 | |
| 1119 SkOpAngle& SkOpAngleSet::push_back() { | |
| 1120 if (!fAngles) { | |
| 1121 fAngles = SkNEW_ARGS(SkChunkAlloc, (2)); | |
| 1122 } | |
| 1123 void* ptr = fAngles->allocThrow(sizeof(SkOpAngle)); | |
| 1124 SkOpAngle* angle = (SkOpAngle*) ptr; | |
| 1125 #if DEBUG_ANGLE | |
| 1126 angle->setID(++fCount); | |
| 1127 #endif | |
| 1128 return *angle; | |
| 1129 } | |
| 1130 | |
| 1131 void SkOpAngleSet::reset() { | |
| 1132 if (fAngles) { | |
| 1133 fAngles->reset(); | |
| 1134 } | |
| 1135 } | |
| OLD | NEW |