| 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 #ifdef SK_SUPPORT_LEGACY_CUBIC_CHOPPER | |
| 229 static SkScalar eval_cubic_coeff(SkScalar A, SkScalar B, SkScalar C, | |
| 230 SkScalar D, SkScalar t) { | |
| 231 return SkScalarMulAdd(SkScalarMulAdd(SkScalarMulAdd(A, t, B), t, C), t, D); | |
| 232 } | |
| 233 | |
| 234 /* Given 4 cubic points (either Xs or Ys), and a target X or Y, compute the | |
| 235 t value such that cubic(t) = target | |
| 236 */ | |
| 237 static bool chopMonoCubicAt(SkScalar c0, SkScalar c1, SkScalar c2, SkScalar c3, | |
| 238 SkScalar target, SkScalar* t) { | |
| 239 // SkASSERT(c0 <= c1 && c1 <= c2 && c2 <= c3); | |
| 240 SkASSERT(c0 < target && target < c3); | |
| 241 | |
| 242 SkScalar D = c0 - target; | |
| 243 SkScalar A = c3 + 3*(c1 - c2) - c0; | |
| 244 SkScalar B = 3*(c2 - c1 - c1 + c0); | |
| 245 SkScalar C = 3*(c1 - c0); | |
| 246 | |
| 247 const SkScalar TOLERANCE = SK_Scalar1 / 4096; | |
| 248 SkScalar minT = 0; | |
| 249 SkScalar maxT = SK_Scalar1; | |
| 250 SkScalar mid; | |
| 251 | |
| 252 // This is a lot of iterations. Is there a faster way? | |
| 253 for (int i = 0; i < 24; i++) { | |
| 254 mid = SkScalarAve(minT, maxT); | |
| 255 SkScalar delta = eval_cubic_coeff(A, B, C, D, mid); | |
| 256 if (delta < 0) { | |
| 257 minT = mid; | |
| 258 delta = -delta; | |
| 259 } else { | |
| 260 maxT = mid; | |
| 261 } | |
| 262 if (delta < TOLERANCE) { | |
| 263 break; | |
| 264 } | |
| 265 } | |
| 266 *t = mid; | |
| 267 // SkDebugf("-- evalCubicAt %d delta %g\n", i, eval_cubic_coeff(A, B, C, D, *
t)); | |
| 268 return true; | |
| 269 } | |
| 270 | |
| 271 static bool chopMonoCubicAtY(SkPoint pts[4], SkScalar y, SkScalar* t) { | |
| 272 return chopMonoCubicAt(pts[0].fY, pts[1].fY, pts[2].fY, pts[3].fY, y, t); | |
| 273 } | |
| 274 | |
| 275 static bool chopMonoCubicAtX(SkPoint pts[4], SkScalar x, SkScalar* t) { | |
| 276 return chopMonoCubicAt(pts[0].fX, pts[1].fX, pts[2].fX, pts[3].fX, x, t); | |
| 277 } | |
| 278 #endif | |
| 279 | |
| 280 // Modify pts[] in place so that it is clipped in Y to the clip rect | 228 // Modify pts[] in place so that it is clipped in Y to the clip rect |
| 281 static void chop_cubic_in_Y(SkPoint pts[4], const SkRect& clip) { | 229 static void chop_cubic_in_Y(SkPoint pts[4], const SkRect& clip) { |
| 282 | 230 |
| 283 // are we partially above | 231 // are we partially above |
| 284 if (pts[0].fY < clip.fTop) { | 232 if (pts[0].fY < clip.fTop) { |
| 285 SkPoint tmp[7]; | 233 SkPoint tmp[7]; |
| 286 #ifdef SK_SUPPORT_LEGACY_CUBIC_CHOPPER | |
| 287 SkScalar t; | |
| 288 if (chopMonoCubicAtY(pts, clip.fTop, &t)) { | |
| 289 SkChopCubicAt(pts, tmp, t); | |
| 290 #else | |
| 291 if (SkChopMonoCubicAtY(pts, clip.fTop, tmp)) { | 234 if (SkChopMonoCubicAtY(pts, clip.fTop, tmp)) { |
| 292 #endif | |
| 293 // tmp[3, 4].fY should all be to the below clip.fTop. | 235 // tmp[3, 4].fY should all be to the below clip.fTop. |
| 294 // Since we can't trust the numerics of | 236 // Since we can't trust the numerics of |
| 295 // the chopper, we force those conditions now | 237 // the chopper, we force those conditions now |
| 296 tmp[3].fY = clip.fTop; | 238 tmp[3].fY = clip.fTop; |
| 297 clamp_ge(tmp[4].fY, clip.fTop); | 239 clamp_ge(tmp[4].fY, clip.fTop); |
| 298 #ifdef SK_SUPPORT_LEGACY_CUBIC_CHOPPER | |
| 299 clamp_ge(tmp[5].fY, clip.fTop); | |
| 300 #endif | |
| 301 | 240 |
| 302 pts[0] = tmp[3]; | 241 pts[0] = tmp[3]; |
| 303 pts[1] = tmp[4]; | 242 pts[1] = tmp[4]; |
| 304 pts[2] = tmp[5]; | 243 pts[2] = tmp[5]; |
| 305 } else { | 244 } else { |
| 306 // if chopMonoCubicAtY failed, then we may have hit inexact numerics | 245 // if chopMonoCubicAtY failed, then we may have hit inexact numerics |
| 307 // so we just clamp against the top | 246 // so we just clamp against the top |
| 308 for (int i = 0; i < 4; i++) { | 247 for (int i = 0; i < 4; i++) { |
| 309 clamp_ge(pts[i].fY, clip.fTop); | 248 clamp_ge(pts[i].fY, clip.fTop); |
| 310 } | 249 } |
| 311 } | 250 } |
| 312 } | 251 } |
| 313 | 252 |
| 314 // are we partially below | 253 // are we partially below |
| 315 if (pts[3].fY > clip.fBottom) { | 254 if (pts[3].fY > clip.fBottom) { |
| 316 SkPoint tmp[7]; | 255 SkPoint tmp[7]; |
| 317 #ifdef SK_SUPPORT_LEGACY_CUBIC_CHOPPER | |
| 318 SkScalar t; | |
| 319 if (chopMonoCubicAtY(pts, clip.fBottom, &t)) { | |
| 320 SkChopCubicAt(pts, tmp, t); | |
| 321 #else | |
| 322 if (SkChopMonoCubicAtY(pts, clip.fBottom, tmp)) { | 256 if (SkChopMonoCubicAtY(pts, clip.fBottom, tmp)) { |
| 323 #endif | |
| 324 tmp[3].fY = clip.fBottom; | 257 tmp[3].fY = clip.fBottom; |
| 325 clamp_le(tmp[2].fY, clip.fBottom); | 258 clamp_le(tmp[2].fY, clip.fBottom); |
| 326 | 259 |
| 327 pts[1] = tmp[1]; | 260 pts[1] = tmp[1]; |
| 328 pts[2] = tmp[2]; | 261 pts[2] = tmp[2]; |
| 329 pts[3] = tmp[3]; | 262 pts[3] = tmp[3]; |
| 330 } else { | 263 } else { |
| 331 // if chopMonoCubicAtY failed, then we may have hit inexact numerics | 264 // if chopMonoCubicAtY failed, then we may have hit inexact numerics |
| 332 // so we just clamp against the bottom | 265 // so we just clamp against the bottom |
| 333 for (int i = 0; i < 4; i++) { | 266 for (int i = 0; i < 4; i++) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 if (pts[0].fX >= clip.fRight) { // wholly to the right | 298 if (pts[0].fX >= clip.fRight) { // wholly to the right |
| 366 if (!this->canCullToTheRight()) { | 299 if (!this->canCullToTheRight()) { |
| 367 this->appendVLine(clip.fRight, pts[0].fY, pts[3].fY, reverse); | 300 this->appendVLine(clip.fRight, pts[0].fY, pts[3].fY, reverse); |
| 368 } | 301 } |
| 369 return; | 302 return; |
| 370 } | 303 } |
| 371 | 304 |
| 372 // are we partially to the left | 305 // are we partially to the left |
| 373 if (pts[0].fX < clip.fLeft) { | 306 if (pts[0].fX < clip.fLeft) { |
| 374 SkPoint tmp[7]; | 307 SkPoint tmp[7]; |
| 375 #ifdef SK_SUPPORT_LEGACY_CUBIC_CHOPPER | |
| 376 SkScalar t; | |
| 377 if (chopMonoCubicAtX(pts, clip.fLeft, &t)) { | |
| 378 SkChopCubicAt(pts, tmp, t); | |
| 379 #else | |
| 380 if (SkChopMonoCubicAtX(pts, clip.fLeft, tmp)) { | 308 if (SkChopMonoCubicAtX(pts, clip.fLeft, tmp)) { |
| 381 #endif | |
| 382 this->appendVLine(clip.fLeft, tmp[0].fY, tmp[3].fY, reverse); | 309 this->appendVLine(clip.fLeft, tmp[0].fY, tmp[3].fY, reverse); |
| 383 | 310 |
| 384 // tmp[3, 4].fX should all be to the right of clip.fLeft. | 311 // tmp[3, 4].fX should all be to the right of clip.fLeft. |
| 385 // Since we can't trust the numerics of | 312 // Since we can't trust the numerics of |
| 386 // the chopper, we force those conditions now | 313 // the chopper, we force those conditions now |
| 387 tmp[3].fX = clip.fLeft; | 314 tmp[3].fX = clip.fLeft; |
| 388 clamp_ge(tmp[4].fX, clip.fLeft); | 315 clamp_ge(tmp[4].fX, clip.fLeft); |
| 389 #ifdef SK_SUPPORT_LEGACY_CUBIC_CHOPPER | |
| 390 clamp_ge(tmp[5].fX, clip.fLeft); | |
| 391 #endif | |
| 392 | 316 |
| 393 pts[0] = tmp[3]; | 317 pts[0] = tmp[3]; |
| 394 pts[1] = tmp[4]; | 318 pts[1] = tmp[4]; |
| 395 pts[2] = tmp[5]; | 319 pts[2] = tmp[5]; |
| 396 } else { | 320 } else { |
| 397 // if chopMonocubicAtY failed, then we may have hit inexact numerics | 321 // if chopMonocubicAtY failed, then we may have hit inexact numerics |
| 398 // so we just clamp against the left | 322 // so we just clamp against the left |
| 399 this->appendVLine(clip.fLeft, pts[0].fY, pts[3].fY, reverse); | 323 this->appendVLine(clip.fLeft, pts[0].fY, pts[3].fY, reverse); |
| 400 return; | 324 return; |
| 401 } | 325 } |
| 402 } | 326 } |
| 403 | 327 |
| 404 // are we partially to the right | 328 // are we partially to the right |
| 405 if (pts[3].fX > clip.fRight) { | 329 if (pts[3].fX > clip.fRight) { |
| 406 SkPoint tmp[7]; | 330 SkPoint tmp[7]; |
| 407 #ifdef SK_SUPPORT_LEGACY_CUBIC_CHOPPER | |
| 408 SkScalar t; | |
| 409 if (chopMonoCubicAtX(pts, clip.fRight, &t)) { | |
| 410 SkChopCubicAt(pts, tmp, t); | |
| 411 #else | |
| 412 if (SkChopMonoCubicAtX(pts, clip.fRight, tmp)) { | 331 if (SkChopMonoCubicAtX(pts, clip.fRight, tmp)) { |
| 413 #endif | |
| 414 tmp[3].fX = clip.fRight; | 332 tmp[3].fX = clip.fRight; |
| 415 clamp_le(tmp[2].fX, clip.fRight); | 333 clamp_le(tmp[2].fX, clip.fRight); |
| 416 #ifdef SK_SUPPORT_LEGACY_CUBIC_CHOPPER | |
| 417 clamp_le(tmp[1].fX, clip.fRight); | |
| 418 #endif | |
| 419 | 334 |
| 420 this->appendCubic(tmp, reverse); | 335 this->appendCubic(tmp, reverse); |
| 421 this->appendVLine(clip.fRight, tmp[3].fY, tmp[6].fY, reverse); | 336 this->appendVLine(clip.fRight, tmp[3].fY, tmp[6].fY, reverse); |
| 422 } else { | 337 } else { |
| 423 // if chopMonoCubicAtX failed, then we may have hit inexact numerics | 338 // if chopMonoCubicAtX failed, then we may have hit inexact numerics |
| 424 // so we just clamp against the right | 339 // so we just clamp against the right |
| 425 this->appendVLine(clip.fRight, pts[0].fY, pts[3].fY, reverse); | 340 this->appendVLine(clip.fRight, pts[0].fY, pts[3].fY, reverse); |
| 426 } | 341 } |
| 427 } else { // wholly inside the clip | 342 } else { // wholly inside the clip |
| 428 this->appendCubic(pts, reverse); | 343 this->appendCubic(pts, reverse); |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 549 assert_monotonic(&pts[0].fY, count); | 464 assert_monotonic(&pts[0].fY, count); |
| 550 } | 465 } |
| 551 } | 466 } |
| 552 | 467 |
| 553 void sk_assert_monotonic_x(const SkPoint pts[], int count) { | 468 void sk_assert_monotonic_x(const SkPoint pts[], int count) { |
| 554 if (count > 1) { | 469 if (count > 1) { |
| 555 assert_monotonic(&pts[0].fX, count); | 470 assert_monotonic(&pts[0].fX, count); |
| 556 } | 471 } |
| 557 } | 472 } |
| 558 #endif | 473 #endif |
| OLD | NEW |