OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2009 The Android Open Source Project | 3 * Copyright 2009 The Android Open Source Project |
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 | 8 |
9 | 9 |
10 #include "SkEdgeClipper.h" | 10 #include "SkEdgeClipper.h" |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 } | 218 } |
219 | 219 |
220 *fCurrVerb = SkPath::kDone_Verb; | 220 *fCurrVerb = SkPath::kDone_Verb; |
221 fCurrPoint = fPoints; | 221 fCurrPoint = fPoints; |
222 fCurrVerb = fVerbs; | 222 fCurrVerb = fVerbs; |
223 return SkPath::kDone_Verb != fVerbs[0]; | 223 return SkPath::kDone_Verb != fVerbs[0]; |
224 } | 224 } |
225 | 225 |
226 /////////////////////////////////////////////////////////////////////////////// | 226 /////////////////////////////////////////////////////////////////////////////// |
227 | 227 |
228 // Modify pts[] in place so that it is clipped in Y to the clip rect | 228 static SkScalar mono_cubic_closestT(const SkScalar src[], SkScalar x) { |
229 static void chop_cubic_in_Y(SkPoint pts[4], const SkRect& clip) { | |
230 | |
231 // are we partially above | |
232 if (pts[0].fY < clip.fTop) { | |
233 SkPoint tmp[7]; | |
234 if (SkChopMonoCubicAtY(pts, clip.fTop, tmp)) { | |
235 // tmp[3, 4].fY should all be to the below clip.fTop. | |
236 // Since we can't trust the numerics of | |
237 // the chopper, we force those conditions now | |
238 tmp[3].fY = clip.fTop; | |
239 clamp_ge(tmp[4].fY, clip.fTop); | |
240 | |
241 pts[0] = tmp[3]; | |
242 pts[1] = tmp[4]; | |
243 pts[2] = tmp[5]; | |
244 } else { | |
245 // if chopMonoCubicAtY failed, then we may have hit inexact numerics | |
246 // so we just clamp against the top | |
247 for (int i = 0; i < 4; i++) { | |
248 clamp_ge(pts[i].fY, clip.fTop); | |
249 } | |
250 } | |
251 } | |
252 | |
253 // are we partially below | |
254 if (pts[3].fY > clip.fBottom) { | |
255 SkPoint tmp[7]; | |
256 if (SkChopMonoCubicAtY(pts, clip.fBottom, tmp)) { | |
257 tmp[3].fY = clip.fBottom; | |
258 clamp_le(tmp[2].fY, clip.fBottom); | |
259 | |
260 pts[1] = tmp[1]; | |
261 pts[2] = tmp[2]; | |
262 pts[3] = tmp[3]; | |
263 } else { | |
264 // if chopMonoCubicAtY failed, then we may have hit inexact numerics | |
265 // so we just clamp against the bottom | |
266 for (int i = 0; i < 4; i++) { | |
267 clamp_le(pts[i].fY, clip.fBottom); | |
268 } | |
269 } | |
270 } | |
271 } | |
272 | |
273 static void chop_mono_cubic_at_x(SkPoint pts[4], SkScalar x, SkPoint tmp[7]) { | |
274 if (SkChopMonoCubicAtX(pts, x, tmp)) { | |
275 return; | |
276 } | |
277 SkScalar t = 0.5f; | 229 SkScalar t = 0.5f; |
278 SkScalar lastT; | 230 SkScalar lastT; |
279 SkScalar bestT SK_INIT_TO_AVOID_WARNING; | 231 SkScalar bestT SK_INIT_TO_AVOID_WARNING; |
280 SkScalar step = 0.25f; | 232 SkScalar step = 0.25f; |
281 SkScalar D = pts[0].fX; | 233 SkScalar D = src[0]; |
282 SkScalar A = pts[3].fX + 3*(pts[1].fX - pts[2].fX) - D; | 234 SkScalar A = src[6] + 3*(src[2] - src[4]) - D; |
283 SkScalar B = 3*(pts[2].fX - pts[1].fX - pts[1].fX + D); | 235 SkScalar B = 3*(src[4] - src[2] - src[2] + D); |
284 SkScalar C = 3*(pts[1].fX - D); | 236 SkScalar C = 3*(src[2] - D); |
285 x -= D; | 237 x -= D; |
286 SkScalar closest = SK_ScalarMax; | 238 SkScalar closest = SK_ScalarMax; |
287 do { | 239 do { |
288 SkScalar loc = ((A * t + B) * t + C) * t; | 240 SkScalar loc = ((A * t + B) * t + C) * t; |
289 SkScalar dist = SkScalarAbs(loc - x); | 241 SkScalar dist = SkScalarAbs(loc - x); |
290 if (closest > dist) { | 242 if (closest > dist) { |
291 closest = dist; | 243 closest = dist; |
292 bestT = t; | 244 bestT = t; |
293 } | 245 } |
294 lastT = t; | 246 lastT = t; |
295 t += loc < x ? step : -step; | 247 t += loc < x ? step : -step; |
296 step *= 0.5f; | 248 step *= 0.5f; |
297 } while (closest > 0.25f && lastT != t); | 249 } while (closest > 0.25f && lastT != t); |
298 SkChopCubicAt(pts, tmp, bestT); | 250 return bestT; |
| 251 } |
| 252 |
| 253 static void chop_mono_cubic_at_y(SkPoint src[4], SkScalar y, SkPoint dst[7]) { |
| 254 if (SkChopMonoCubicAtY(src, y, dst)) { |
| 255 return; |
| 256 } |
| 257 SkChopCubicAt(src, dst, mono_cubic_closestT(&src->fY, y)); |
| 258 } |
| 259 |
| 260 // Modify pts[] in place so that it is clipped in Y to the clip rect |
| 261 static void chop_cubic_in_Y(SkPoint pts[4], const SkRect& clip) { |
| 262 |
| 263 // are we partially above |
| 264 if (pts[0].fY < clip.fTop) { |
| 265 SkPoint tmp[7]; |
| 266 chop_mono_cubic_at_y(pts, clip.fTop, tmp); |
| 267 // tmp[3, 4].fY should all be to the below clip.fTop. |
| 268 // Since we can't trust the numerics of |
| 269 // the chopper, we force those conditions now |
| 270 tmp[3].fY = clip.fTop; |
| 271 clamp_ge(tmp[4].fY, clip.fTop); |
| 272 |
| 273 pts[0] = tmp[3]; |
| 274 pts[1] = tmp[4]; |
| 275 pts[2] = tmp[5]; |
| 276 } |
| 277 |
| 278 // are we partially below |
| 279 if (pts[3].fY > clip.fBottom) { |
| 280 SkPoint tmp[7]; |
| 281 chop_mono_cubic_at_y(pts, clip.fBottom, tmp); |
| 282 tmp[3].fY = clip.fBottom; |
| 283 clamp_le(tmp[2].fY, clip.fBottom); |
| 284 |
| 285 pts[1] = tmp[1]; |
| 286 pts[2] = tmp[2]; |
| 287 pts[3] = tmp[3]; |
| 288 } |
| 289 } |
| 290 |
| 291 static void chop_mono_cubic_at_x(SkPoint src[4], SkScalar x, SkPoint dst[7]) { |
| 292 if (SkChopMonoCubicAtX(src, x, dst)) { |
| 293 return; |
| 294 } |
| 295 SkChopCubicAt(src, dst, mono_cubic_closestT(&src->fX, x)); |
299 } | 296 } |
300 | 297 |
301 // srcPts[] must be monotonic in X and Y | 298 // srcPts[] must be monotonic in X and Y |
302 void SkEdgeClipper::clipMonoCubic(const SkPoint src[4], const SkRect& clip) { | 299 void SkEdgeClipper::clipMonoCubic(const SkPoint src[4], const SkRect& clip) { |
303 SkPoint pts[4]; | 300 SkPoint pts[4]; |
304 bool reverse = sort_increasing_Y(pts, src, 4); | 301 bool reverse = sort_increasing_Y(pts, src, 4); |
305 | 302 |
306 // are we completely above or below | 303 // are we completely above or below |
307 if (pts[3].fY <= clip.fTop || pts[0].fY >= clip.fBottom) { | 304 if (pts[3].fY <= clip.fTop || pts[0].fY >= clip.fBottom) { |
308 return; | 305 return; |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
481 assert_monotonic(&pts[0].fY, count); | 478 assert_monotonic(&pts[0].fY, count); |
482 } | 479 } |
483 } | 480 } |
484 | 481 |
485 void sk_assert_monotonic_x(const SkPoint pts[], int count) { | 482 void sk_assert_monotonic_x(const SkPoint pts[], int count) { |
486 if (count > 1) { | 483 if (count > 1) { |
487 assert_monotonic(&pts[0].fX, count); | 484 assert_monotonic(&pts[0].fX, count); |
488 } | 485 } |
489 } | 486 } |
490 #endif | 487 #endif |
OLD | NEW |