| 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 | 7 |
| 8 #include "SkIntersections.h" | 8 #include "SkIntersections.h" |
| 9 | 9 |
| 10 void SkIntersections::append(const SkIntersections& i) { | 10 int SkIntersections::closestTo(double rangeStart, double rangeEnd, const SkDPoin
t& testPt, |
| 11 for (int index = 0; index < i.fUsed; ++index) { | 11 double* closestDist) const { |
| 12 insert(i[0][index], i[1][index], i.pt(index)); | 12 int closest = -1; |
| 13 *closestDist = SK_ScalarMax; |
| 14 for (int index = 0; index < fUsed; ++index) { |
| 15 if (!between(rangeStart, fT[0][index], rangeEnd)) { |
| 16 continue; |
| 17 } |
| 18 const SkDPoint& iPt = fPt[index]; |
| 19 double dist = testPt.distanceSquared(iPt); |
| 20 if (*closestDist > dist) { |
| 21 *closestDist = dist; |
| 22 closest = index; |
| 23 } |
| 13 } | 24 } |
| 25 return closest; |
| 14 } | 26 } |
| 15 | 27 |
| 16 int (SkIntersections::* const CurveVertical[])(const SkPoint[], SkScalar, SkScal
ar, SkScalar, bool) = { | 28 // called only by test code |
| 17 NULL, | |
| 18 &SkIntersections::verticalLine, | |
| 19 &SkIntersections::verticalQuad, | |
| 20 &SkIntersections::verticalCubic | |
| 21 }; | |
| 22 | |
| 23 int ( SkIntersections::* const CurveRay[])(const SkPoint[], const SkDLine&) = { | |
| 24 NULL, | |
| 25 &SkIntersections::lineRay, | |
| 26 &SkIntersections::quadRay, | |
| 27 &SkIntersections::cubicRay | |
| 28 }; | |
| 29 | |
| 30 int SkIntersections::coincidentUsed() const { | 29 int SkIntersections::coincidentUsed() const { |
| 31 if (!fIsCoincident[0]) { | 30 if (!fIsCoincident[0]) { |
| 32 SkASSERT(!fIsCoincident[1]); | 31 SkASSERT(!fIsCoincident[1]); |
| 33 return 0; | 32 return 0; |
| 34 } | 33 } |
| 35 int count = 0; | 34 int count = 0; |
| 36 SkDEBUGCODE(int count2 = 0;) | 35 SkDEBUGCODE(int count2 = 0;) |
| 37 for (int index = 0; index < fUsed; ++index) { | 36 for (int index = 0; index < fUsed; ++index) { |
| 38 if (fIsCoincident[0] & (1 << index)) { | 37 if (fIsCoincident[0] & (1 << index)) { |
| 39 ++count; | 38 ++count; |
| 40 } | 39 } |
| 41 #ifdef SK_DEBUG | 40 #ifdef SK_DEBUG |
| 42 if (fIsCoincident[1] & (1 << index)) { | 41 if (fIsCoincident[1] & (1 << index)) { |
| 43 ++count2; | 42 ++count2; |
| 44 } | 43 } |
| 45 #endif | 44 #endif |
| 46 } | 45 } |
| 47 SkASSERT(count == count2); | 46 SkASSERT(count == count2); |
| 48 return count; | 47 return count; |
| 49 } | 48 } |
| 50 | 49 |
| 51 int SkIntersections::cubicRay(const SkPoint pts[4], const SkDLine& line) { | 50 int (SkIntersections::* const CurveVertical[])(const SkPoint[], SkScalar, SkScal
ar, SkScalar, bool) = { |
| 52 SkDCubic cubic; | 51 NULL, |
| 53 cubic.set(pts); | 52 &SkIntersections::verticalLine, |
| 54 fMax = 3; | 53 &SkIntersections::verticalQuad, |
| 55 return intersectRay(cubic, line); | 54 &SkIntersections::verticalCubic |
| 56 } | 55 }; |
| 57 | 56 |
| 58 void SkIntersections::flip() { | 57 void SkIntersections::flip() { |
| 59 for (int index = 0; index < fUsed; ++index) { | 58 for (int index = 0; index < fUsed; ++index) { |
| 60 fT[1][index] = 1 - fT[1][index]; | 59 fT[1][index] = 1 - fT[1][index]; |
| 61 } | 60 } |
| 62 } | 61 } |
| 63 | 62 |
| 64 int SkIntersections::insert(double one, double two, const SkDPoint& pt) { | 63 int SkIntersections::insert(double one, double two, const SkDPoint& pt) { |
| 65 if (fIsCoincident[0] == 3 && between(fT[0][0], one, fT[0][1])) { | 64 if (fIsCoincident[0] == 3 && between(fT[0][0], one, fT[0][1])) { |
| 66 // For now, don't allow a mix of coincident and non-coincident intersect
ions | 65 // For now, don't allow a mix of coincident and non-coincident intersect
ions |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 } | 97 } |
| 99 if (fUsed >= fMax) { | 98 if (fUsed >= fMax) { |
| 100 SkASSERT(0); // FIXME : this error, if it is to be handled at runtime i
n release, must | 99 SkASSERT(0); // FIXME : this error, if it is to be handled at runtime i
n release, must |
| 101 // be propagated all the way back down to the caller, and
return failure. | 100 // be propagated all the way back down to the caller, and
return failure. |
| 102 fUsed = 0; | 101 fUsed = 0; |
| 103 return 0; | 102 return 0; |
| 104 } | 103 } |
| 105 int remaining = fUsed - index; | 104 int remaining = fUsed - index; |
| 106 if (remaining > 0) { | 105 if (remaining > 0) { |
| 107 memmove(&fPt[index + 1], &fPt[index], sizeof(fPt[0]) * remaining); | 106 memmove(&fPt[index + 1], &fPt[index], sizeof(fPt[0]) * remaining); |
| 108 memmove(&fPt2[index + 1], &fPt2[index], sizeof(fPt2[0]) * remaining); | |
| 109 memmove(&fT[0][index + 1], &fT[0][index], sizeof(fT[0][0]) * remaining); | 107 memmove(&fT[0][index + 1], &fT[0][index], sizeof(fT[0][0]) * remaining); |
| 110 memmove(&fT[1][index + 1], &fT[1][index], sizeof(fT[1][0]) * remaining); | 108 memmove(&fT[1][index + 1], &fT[1][index], sizeof(fT[1][0]) * remaining); |
| 111 int clearMask = ~((1 << index) - 1); | 109 int clearMask = ~((1 << index) - 1); |
| 112 fIsCoincident[0] += fIsCoincident[0] & clearMask; | 110 fIsCoincident[0] += fIsCoincident[0] & clearMask; |
| 113 fIsCoincident[1] += fIsCoincident[1] & clearMask; | 111 fIsCoincident[1] += fIsCoincident[1] & clearMask; |
| 114 } | 112 } |
| 115 fPt[index] = pt; | 113 fPt[index] = pt; |
| 116 SkASSERT(one >= 0 && one <= 1); | 114 SkASSERT(one >= 0 && one <= 1); |
| 117 SkASSERT(two >= 0 && two <= 1); | 115 SkASSERT(two >= 0 && two <= 1); |
| 118 fT[0][index] = one; | 116 fT[0][index] = one; |
| 119 fT[1][index] = two; | 117 fT[1][index] = two; |
| 120 ++fUsed; | 118 ++fUsed; |
| 121 return index; | 119 return index; |
| 122 } | 120 } |
| 123 | 121 |
| 124 void SkIntersections::insertNear(double one, double two, const SkDPoint& pt1, co
nst SkDPoint& pt2) { | 122 void SkIntersections::insertNear(double one, double two, const SkDPoint& pt1, co
nst SkDPoint& pt2) { |
| 125 SkASSERT(one == 0 || one == 1); | 123 SkASSERT(one == 0 || one == 1); |
| 126 SkASSERT(two == 0 || two == 1); | 124 SkASSERT(two == 0 || two == 1); |
| 127 SkASSERT(pt1 != pt2); | 125 SkASSERT(pt1 != pt2); |
| 128 SkASSERT(fNearlySame[(int) one]); | 126 fNearlySame[one ? 1 : 0] = true; |
| 129 (void) insert(one, two, pt1); | 127 (void) insert(one, two, pt1); |
| 130 fPt2[one ? fUsed - 1 : 0] = pt2; | 128 fPt2[one ? 1 : 0] = pt2; |
| 131 } | 129 } |
| 132 | 130 |
| 133 void SkIntersections::insertCoincident(double one, double two, const SkDPoint& p
t) { | 131 int SkIntersections::insertCoincident(double one, double two, const SkDPoint& pt
) { |
| 134 int index = insertSwap(one, two, pt); | 132 int index = insertSwap(one, two, pt); |
| 133 if (index >= 0) { |
| 134 setCoincident(index); |
| 135 } |
| 136 return index; |
| 137 } |
| 138 |
| 139 void SkIntersections::setCoincident(int index) { |
| 140 SkASSERT(index >= 0); |
| 135 int bit = 1 << index; | 141 int bit = 1 << index; |
| 136 fIsCoincident[0] |= bit; | 142 fIsCoincident[0] |= bit; |
| 137 fIsCoincident[1] |= bit; | 143 fIsCoincident[1] |= bit; |
| 138 } | 144 } |
| 139 | 145 |
| 140 int SkIntersections::lineRay(const SkPoint pts[2], const SkDLine& line) { | 146 void SkIntersections::merge(const SkIntersections& a, int aIndex, const SkInters
ections& b, |
| 141 SkDLine l; | 147 int bIndex) { |
| 142 l.set(pts); | 148 this->reset(); |
| 143 fMax = 2; | 149 fT[0][0] = a.fT[0][aIndex]; |
| 144 return intersectRay(l, line); | 150 fT[1][0] = b.fT[0][bIndex]; |
| 151 fPt[0] = a.fPt[aIndex]; |
| 152 fPt2[0] = b.fPt[bIndex]; |
| 153 fUsed = 1; |
| 145 } | 154 } |
| 146 | 155 |
| 147 void SkIntersections::offset(int base, double start, double end) { | 156 int SkIntersections::mostOutside(double rangeStart, double rangeEnd, const SkDPo
int& origin) const { |
| 148 for (int index = base; index < fUsed; ++index) { | 157 int result = -1; |
| 149 double val = fT[fSwap][index]; | 158 for (int index = 0; index < fUsed; ++index) { |
| 150 val *= end - start; | 159 if (!between(rangeStart, fT[0][index], rangeEnd)) { |
| 151 val += start; | 160 continue; |
| 152 fT[fSwap][index] = val; | 161 } |
| 162 if (result < 0) { |
| 163 result = index; |
| 164 continue; |
| 165 } |
| 166 SkDVector best = fPt[result] - origin; |
| 167 SkDVector test = fPt[index] - origin; |
| 168 if (test.crossCheck(best) < 0) { |
| 169 result = index; |
| 170 } |
| 153 } | 171 } |
| 154 } | 172 return result; |
| 155 | |
| 156 int SkIntersections::quadRay(const SkPoint pts[3], const SkDLine& line) { | |
| 157 SkDQuad quad; | |
| 158 quad.set(pts); | |
| 159 fMax = 2; | |
| 160 return intersectRay(quad, line); | |
| 161 } | 173 } |
| 162 | 174 |
| 163 void SkIntersections::quickRemoveOne(int index, int replace) { | 175 void SkIntersections::quickRemoveOne(int index, int replace) { |
| 164 if (index < replace) { | 176 if (index < replace) { |
| 165 fT[0][index] = fT[0][replace]; | 177 fT[0][index] = fT[0][replace]; |
| 166 } | 178 } |
| 167 } | 179 } |
| 168 | 180 |
| 169 void SkIntersections::removeOne(int index) { | 181 void SkIntersections::removeOne(int index) { |
| 170 int remaining = --fUsed - index; | 182 int remaining = --fUsed - index; |
| 171 if (remaining <= 0) { | 183 if (remaining <= 0) { |
| 172 return; | 184 return; |
| 173 } | 185 } |
| 174 memmove(&fPt[index], &fPt[index + 1], sizeof(fPt[0]) * remaining); | 186 memmove(&fPt[index], &fPt[index + 1], sizeof(fPt[0]) * remaining); |
| 175 memmove(&fPt2[index], &fPt2[index + 1], sizeof(fPt2[0]) * remaining); | |
| 176 memmove(&fT[0][index], &fT[0][index + 1], sizeof(fT[0][0]) * remaining); | 187 memmove(&fT[0][index], &fT[0][index + 1], sizeof(fT[0][0]) * remaining); |
| 177 memmove(&fT[1][index], &fT[1][index + 1], sizeof(fT[1][0]) * remaining); | 188 memmove(&fT[1][index], &fT[1][index + 1], sizeof(fT[1][0]) * remaining); |
| 178 // SkASSERT(fIsCoincident[0] == 0); | 189 // SkASSERT(fIsCoincident[0] == 0); |
| 179 int coBit = fIsCoincident[0] & (1 << index); | 190 int coBit = fIsCoincident[0] & (1 << index); |
| 180 fIsCoincident[0] -= ((fIsCoincident[0] >> 1) & ~((1 << index) - 1)) + coBit; | 191 fIsCoincident[0] -= ((fIsCoincident[0] >> 1) & ~((1 << index) - 1)) + coBit; |
| 181 SkASSERT(!(coBit ^ (fIsCoincident[1] & (1 << index)))); | 192 SkASSERT(!(coBit ^ (fIsCoincident[1] & (1 << index)))); |
| 182 fIsCoincident[1] -= ((fIsCoincident[1] >> 1) & ~((1 << index) - 1)) + coBit; | 193 fIsCoincident[1] -= ((fIsCoincident[1] >> 1) & ~((1 << index) - 1)) + coBit; |
| 183 } | 194 } |
| 184 | 195 |
| 185 void SkIntersections::swapPts() { | |
| 186 int index; | |
| 187 for (index = 0; index < fUsed; ++index) { | |
| 188 SkTSwap(fT[0][index], fT[1][index]); | |
| 189 } | |
| 190 } | |
| 191 | |
| 192 int SkIntersections::verticalLine(const SkPoint a[2], SkScalar top, SkScalar bot
tom, | 196 int SkIntersections::verticalLine(const SkPoint a[2], SkScalar top, SkScalar bot
tom, |
| 193 SkScalar x, bool flipped) { | 197 SkScalar x, bool flipped) { |
| 194 SkDLine line; | 198 SkDLine line; |
| 195 line.set(a); | 199 line.set(a); |
| 196 return vertical(line, top, bottom, x, flipped); | 200 return vertical(line, top, bottom, x, flipped); |
| 197 } | 201 } |
| 198 | 202 |
| 199 int SkIntersections::verticalQuad(const SkPoint a[3], SkScalar top, SkScalar bot
tom, | 203 int SkIntersections::verticalQuad(const SkPoint a[3], SkScalar top, SkScalar bot
tom, |
| 200 SkScalar x, bool flipped) { | 204 SkScalar x, bool flipped) { |
| 201 SkDQuad quad; | 205 SkDQuad quad; |
| 202 quad.set(a); | 206 quad.set(a); |
| 203 return vertical(quad, top, bottom, x, flipped); | 207 return vertical(quad, top, bottom, x, flipped); |
| 204 } | 208 } |
| 205 | 209 |
| 206 int SkIntersections::verticalCubic(const SkPoint a[4], SkScalar top, SkScalar bo
ttom, | 210 int SkIntersections::verticalCubic(const SkPoint a[4], SkScalar top, SkScalar bo
ttom, |
| 207 SkScalar x, bool flipped) { | 211 SkScalar x, bool flipped) { |
| 208 SkDCubic cubic; | 212 SkDCubic cubic; |
| 209 cubic.set(a); | 213 cubic.set(a); |
| 210 return vertical(cubic, top, bottom, x, flipped); | 214 return vertical(cubic, top, bottom, x, flipped); |
| 211 } | 215 } |
| OLD | NEW |