OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 #include "SkLineClipper.h" | 8 #include "SkLineClipper.h" |
9 | 9 |
10 template <typename T> T pin_unsorted(T value, T limit0, T limit1) { | 10 template <typename T> T pin_unsorted(T value, T limit0, T limit1) { |
(...skipping 10 matching lines...) Expand all Loading... |
21 } | 21 } |
22 return value; | 22 return value; |
23 } | 23 } |
24 | 24 |
25 // return X coordinate of intersection with horizontal line at Y | 25 // return X coordinate of intersection with horizontal line at Y |
26 static SkScalar sect_with_horizontal(const SkPoint src[2], SkScalar Y) { | 26 static SkScalar sect_with_horizontal(const SkPoint src[2], SkScalar Y) { |
27 SkScalar dy = src[1].fY - src[0].fY; | 27 SkScalar dy = src[1].fY - src[0].fY; |
28 if (SkScalarNearlyZero(dy)) { | 28 if (SkScalarNearlyZero(dy)) { |
29 return SkScalarAve(src[0].fX, src[1].fX); | 29 return SkScalarAve(src[0].fX, src[1].fX); |
30 } else { | 30 } else { |
31 #ifdef SK_SCALAR_IS_FLOAT | |
32 // need the extra precision so we don't compute a value that exceeds | 31 // need the extra precision so we don't compute a value that exceeds |
33 // our original limits | 32 // our original limits |
34 double X0 = src[0].fX; | 33 double X0 = src[0].fX; |
35 double Y0 = src[0].fY; | 34 double Y0 = src[0].fY; |
36 double X1 = src[1].fX; | 35 double X1 = src[1].fX; |
37 double Y1 = src[1].fY; | 36 double Y1 = src[1].fY; |
38 double result = X0 + ((double)Y - Y0) * (X1 - X0) / (Y1 - Y0); | 37 double result = X0 + ((double)Y - Y0) * (X1 - X0) / (Y1 - Y0); |
39 | 38 |
40 // The computed X value might still exceed [X0..X1] due to quantum flux | 39 // The computed X value might still exceed [X0..X1] due to quantum flux |
41 // when the doubles were added and subtracted, so we have to pin the | 40 // when the doubles were added and subtracted, so we have to pin the |
42 // answer :( | 41 // answer :( |
43 return (float)pin_unsorted(result, X0, X1); | 42 return (float)pin_unsorted(result, X0, X1); |
44 #else | |
45 return src[0].fX + SkScalarMulDiv(Y - src[0].fY, src[1].fX - src[0].fX, | |
46 dy); | |
47 #endif | |
48 } | 43 } |
49 } | 44 } |
50 | 45 |
51 // return Y coordinate of intersection with vertical line at X | 46 // return Y coordinate of intersection with vertical line at X |
52 static SkScalar sect_with_vertical(const SkPoint src[2], SkScalar X) { | 47 static SkScalar sect_with_vertical(const SkPoint src[2], SkScalar X) { |
53 SkScalar dx = src[1].fX - src[0].fX; | 48 SkScalar dx = src[1].fX - src[0].fX; |
54 if (SkScalarNearlyZero(dx)) { | 49 if (SkScalarNearlyZero(dx)) { |
55 return SkScalarAve(src[0].fY, src[1].fY); | 50 return SkScalarAve(src[0].fY, src[1].fY); |
56 } else { | 51 } else { |
57 #ifdef SK_SCALAR_IS_FLOAT | |
58 // need the extra precision so we don't compute a value that exceeds | 52 // need the extra precision so we don't compute a value that exceeds |
59 // our original limits | 53 // our original limits |
60 double X0 = src[0].fX; | 54 double X0 = src[0].fX; |
61 double Y0 = src[0].fY; | 55 double Y0 = src[0].fY; |
62 double X1 = src[1].fX; | 56 double X1 = src[1].fX; |
63 double Y1 = src[1].fY; | 57 double Y1 = src[1].fY; |
64 double result = Y0 + ((double)X - X0) * (Y1 - Y0) / (X1 - X0); | 58 double result = Y0 + ((double)X - X0) * (Y1 - Y0) / (X1 - X0); |
65 return (float)result; | 59 return (float)result; |
66 #else | |
67 return src[0].fY + SkScalarMulDiv(X - src[0].fX, src[1].fY - src[0].fY, | |
68 dx); | |
69 #endif | |
70 } | 60 } |
71 } | 61 } |
72 | 62 |
73 /////////////////////////////////////////////////////////////////////////////// | 63 /////////////////////////////////////////////////////////////////////////////// |
74 | 64 |
75 static inline bool nestedLT(SkScalar a, SkScalar b, SkScalar dim) { | 65 static inline bool nestedLT(SkScalar a, SkScalar b, SkScalar dim) { |
76 return a <= b && (a < b || dim > 0); | 66 return a <= b && (a < b || dim > 0); |
77 } | 67 } |
78 | 68 |
79 // returns true if outer contains inner, even if inner is empty. | 69 // returns true if outer contains inner, even if inner is empty. |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 static bool is_between_unsorted(SkScalar value, | 150 static bool is_between_unsorted(SkScalar value, |
161 SkScalar limit0, SkScalar limit1) { | 151 SkScalar limit0, SkScalar limit1) { |
162 if (limit0 < limit1) { | 152 if (limit0 < limit1) { |
163 return limit0 <= value && value <= limit1; | 153 return limit0 <= value && value <= limit1; |
164 } else { | 154 } else { |
165 return limit1 <= value && value <= limit0; | 155 return limit1 <= value && value <= limit0; |
166 } | 156 } |
167 } | 157 } |
168 #endif | 158 #endif |
169 | 159 |
170 #ifdef SK_SCALAR_IS_FLOAT | |
171 #ifdef SK_DEBUG | 160 #ifdef SK_DEBUG |
172 // This is an example of why we need to pin the result computed in | 161 // This is an example of why we need to pin the result computed in |
173 // sect_with_horizontal. If we didn't explicitly pin, is_between_unsorted would | 162 // sect_with_horizontal. If we didn't explicitly pin, is_between_unsorted would |
174 // fail. | 163 // fail. |
175 // | 164 // |
176 static void sect_with_horizontal_test_for_pin_results() { | 165 static void sect_with_horizontal_test_for_pin_results() { |
177 const SkPoint pts[] = { | 166 const SkPoint pts[] = { |
178 { -540000, -720000 }, | 167 { -540000, -720000 }, |
179 { -9.10000017e-05f, 9.99999996e-13f } | 168 { -9.10000017e-05f, 9.99999996e-13f } |
180 }; | 169 }; |
181 float x = sect_with_horizontal(pts, 0); | 170 float x = sect_with_horizontal(pts, 0); |
182 SkASSERT(is_between_unsorted(x, pts[0].fX, pts[1].fX)); | 171 SkASSERT(is_between_unsorted(x, pts[0].fX, pts[1].fX)); |
183 } | 172 } |
184 #endif | 173 #endif |
185 #endif | |
186 | 174 |
187 int SkLineClipper::ClipLine(const SkPoint pts[], const SkRect& clip, | 175 int SkLineClipper::ClipLine(const SkPoint pts[], const SkRect& clip, |
188 SkPoint lines[]) { | 176 SkPoint lines[]) { |
189 #ifdef SK_SCALAR_IS_FLOAT | |
190 #ifdef SK_DEBUG | 177 #ifdef SK_DEBUG |
191 { | 178 { |
192 static bool gOnce; | 179 static bool gOnce; |
193 if (!gOnce) { | 180 if (!gOnce) { |
194 sect_with_horizontal_test_for_pin_results(); | 181 sect_with_horizontal_test_for_pin_results(); |
195 gOnce = true; | 182 gOnce = true; |
196 } | 183 } |
197 } | 184 } |
198 #endif | 185 #endif |
199 #endif | |
200 | 186 |
201 int index0, index1; | 187 int index0, index1; |
202 | 188 |
203 if (pts[0].fY < pts[1].fY) { | 189 if (pts[0].fY < pts[1].fY) { |
204 index0 = 0; | 190 index0 = 0; |
205 index1 = 1; | 191 index1 = 1; |
206 } else { | 192 } else { |
207 index0 = 1; | 193 index0 = 1; |
208 index1 = 0; | 194 index1 = 0; |
209 } | 195 } |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 if (reverse) { | 274 if (reverse) { |
289 // copy the pts in reverse order to maintain winding order | 275 // copy the pts in reverse order to maintain winding order |
290 for (int i = 0; i <= lineCount; i++) { | 276 for (int i = 0; i <= lineCount; i++) { |
291 lines[lineCount - i] = result[i]; | 277 lines[lineCount - i] = result[i]; |
292 } | 278 } |
293 } else { | 279 } else { |
294 memcpy(lines, result, (lineCount + 1) * sizeof(SkPoint)); | 280 memcpy(lines, result, (lineCount + 1) * sizeof(SkPoint)); |
295 } | 281 } |
296 return lineCount; | 282 return lineCount; |
297 } | 283 } |
OLD | NEW |