| 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 |