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 |