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 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
263 } else { | 263 } else { |
264 // if chopMonoCubicAtY failed, then we may have hit inexact numerics | 264 // if chopMonoCubicAtY failed, then we may have hit inexact numerics |
265 // so we just clamp against the bottom | 265 // so we just clamp against the bottom |
266 for (int i = 0; i < 4; i++) { | 266 for (int i = 0; i < 4; i++) { |
267 clamp_le(pts[i].fY, clip.fBottom); | 267 clamp_le(pts[i].fY, clip.fBottom); |
268 } | 268 } |
269 } | 269 } |
270 } | 270 } |
271 } | 271 } |
272 | 272 |
273 static void chop_mono_cubic_at_x(SkPoint pts[4], SkScalar x, SkPoint tmp[7]) { | |
reed1
2015/08/20 14:24:45
perhaps rename
pts -> src or orig
tmp -> dst or ch
| |
274 if (SkChopMonoCubicAtX(pts, x, tmp)) { | |
275 return; | |
276 } | |
277 SkScalar t = 0.5f; | |
278 SkScalar lastT; | |
279 SkScalar bestT SK_INIT_TO_AVOID_WARNING; | |
280 SkScalar step = 0.25f; | |
281 SkScalar D = pts[0].fX; | |
282 SkScalar A = pts[3].fX + 3*(pts[1].fX - pts[2].fX) - D; | |
283 SkScalar B = 3*(pts[2].fX - pts[1].fX - pts[1].fX + D); | |
284 SkScalar C = 3*(pts[1].fX - D); | |
285 x -= D; | |
286 SkScalar closest = SK_ScalarMax; | |
287 do { | |
288 SkScalar loc = ((A * t + B) * t + C) * t; | |
289 SkScalar dist = SkScalarAbs(loc - x); | |
290 if (closest > dist) { | |
291 closest = dist; | |
292 bestT = t; | |
293 } | |
294 lastT = t; | |
295 t += loc < x ? step : -step; | |
296 step *= 0.5f; | |
297 } while (closest > 0.25f && lastT != t); | |
298 SkChopCubicAt(pts, tmp, bestT); | |
299 } | |
300 | |
273 // srcPts[] must be monotonic in X and Y | 301 // srcPts[] must be monotonic in X and Y |
274 void SkEdgeClipper::clipMonoCubic(const SkPoint src[4], const SkRect& clip) { | 302 void SkEdgeClipper::clipMonoCubic(const SkPoint src[4], const SkRect& clip) { |
275 SkPoint pts[4]; | 303 SkPoint pts[4]; |
276 bool reverse = sort_increasing_Y(pts, src, 4); | 304 bool reverse = sort_increasing_Y(pts, src, 4); |
277 | 305 |
278 // are we completely above or below | 306 // are we completely above or below |
279 if (pts[3].fY <= clip.fTop || pts[0].fY >= clip.fBottom) { | 307 if (pts[3].fY <= clip.fTop || pts[0].fY >= clip.fBottom) { |
280 return; | 308 return; |
281 } | 309 } |
282 | 310 |
(...skipping 15 matching lines...) Expand all Loading... | |
298 if (pts[0].fX >= clip.fRight) { // wholly to the right | 326 if (pts[0].fX >= clip.fRight) { // wholly to the right |
299 if (!this->canCullToTheRight()) { | 327 if (!this->canCullToTheRight()) { |
300 this->appendVLine(clip.fRight, pts[0].fY, pts[3].fY, reverse); | 328 this->appendVLine(clip.fRight, pts[0].fY, pts[3].fY, reverse); |
301 } | 329 } |
302 return; | 330 return; |
303 } | 331 } |
304 | 332 |
305 // are we partially to the left | 333 // are we partially to the left |
306 if (pts[0].fX < clip.fLeft) { | 334 if (pts[0].fX < clip.fLeft) { |
307 SkPoint tmp[7]; | 335 SkPoint tmp[7]; |
308 if (SkChopMonoCubicAtX(pts, clip.fLeft, tmp)) { | 336 chop_mono_cubic_at_x(pts, clip.fLeft, tmp); |
309 this->appendVLine(clip.fLeft, tmp[0].fY, tmp[3].fY, reverse); | 337 this->appendVLine(clip.fLeft, tmp[0].fY, tmp[3].fY, reverse); |
310 | 338 |
311 // tmp[3, 4].fX should all be to the right of clip.fLeft. | 339 // tmp[3, 4].fX should all be to the right of clip.fLeft. |
312 // Since we can't trust the numerics of | 340 // Since we can't trust the numerics of |
313 // the chopper, we force those conditions now | 341 // the chopper, we force those conditions now |
314 tmp[3].fX = clip.fLeft; | 342 tmp[3].fX = clip.fLeft; |
315 clamp_ge(tmp[4].fX, clip.fLeft); | 343 clamp_ge(tmp[4].fX, clip.fLeft); |
316 | 344 |
317 pts[0] = tmp[3]; | 345 pts[0] = tmp[3]; |
318 pts[1] = tmp[4]; | 346 pts[1] = tmp[4]; |
319 pts[2] = tmp[5]; | 347 pts[2] = tmp[5]; |
320 } else { | |
321 // if chopMonocubicAtY failed, then we may have hit inexact numerics | |
322 // so we just clamp against the left | |
323 this->appendVLine(clip.fLeft, pts[0].fY, pts[3].fY, reverse); | |
324 return; | |
325 } | |
326 } | 348 } |
327 | 349 |
328 // are we partially to the right | 350 // are we partially to the right |
329 if (pts[3].fX > clip.fRight) { | 351 if (pts[3].fX > clip.fRight) { |
330 SkPoint tmp[7]; | 352 SkPoint tmp[7]; |
331 if (SkChopMonoCubicAtX(pts, clip.fRight, tmp)) { | 353 chop_mono_cubic_at_x(pts, clip.fRight, tmp); |
332 tmp[3].fX = clip.fRight; | 354 tmp[3].fX = clip.fRight; |
333 clamp_le(tmp[2].fX, clip.fRight); | 355 clamp_le(tmp[2].fX, clip.fRight); |
334 | 356 |
335 this->appendCubic(tmp, reverse); | 357 this->appendCubic(tmp, reverse); |
336 this->appendVLine(clip.fRight, tmp[3].fY, tmp[6].fY, reverse); | 358 this->appendVLine(clip.fRight, tmp[3].fY, tmp[6].fY, reverse); |
337 } else { | |
338 // if chopMonoCubicAtX failed, then we may have hit inexact numerics | |
339 // so we just clamp against the right | |
340 this->appendVLine(clip.fRight, pts[0].fY, pts[3].fY, reverse); | |
341 } | |
342 } else { // wholly inside the clip | 359 } else { // wholly inside the clip |
343 this->appendCubic(pts, reverse); | 360 this->appendCubic(pts, reverse); |
344 } | 361 } |
345 } | 362 } |
346 | 363 |
347 bool SkEdgeClipper::clipCubic(const SkPoint srcPts[4], const SkRect& clip) { | 364 bool SkEdgeClipper::clipCubic(const SkPoint srcPts[4], const SkRect& clip) { |
348 fCurrPoint = fPoints; | 365 fCurrPoint = fPoints; |
349 fCurrVerb = fVerbs; | 366 fCurrVerb = fVerbs; |
350 | 367 |
351 SkRect bounds; | 368 SkRect bounds; |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
464 assert_monotonic(&pts[0].fY, count); | 481 assert_monotonic(&pts[0].fY, count); |
465 } | 482 } |
466 } | 483 } |
467 | 484 |
468 void sk_assert_monotonic_x(const SkPoint pts[], int count) { | 485 void sk_assert_monotonic_x(const SkPoint pts[], int count) { |
469 if (count > 1) { | 486 if (count > 1) { |
470 assert_monotonic(&pts[0].fX, count); | 487 assert_monotonic(&pts[0].fX, count); |
471 } | 488 } |
472 } | 489 } |
473 #endif | 490 #endif |
OLD | NEW |