Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkScan.h" | 8 #include "SkScan.h" |
| 9 #include "SkBlitter.h" | 9 #include "SkBlitter.h" |
| 10 #include "SkRasterClip.h" | 10 #include "SkRasterClip.h" |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 341 than a pixel. | 341 than a pixel. |
| 342 */ | 342 */ |
| 343 int level = (33 - SkCLZ(d)) >> 1; | 343 int level = (33 - SkCLZ(d)) >> 1; |
| 344 // sanity check on level (from the previous version) | 344 // sanity check on level (from the previous version) |
| 345 if (level > kMaxQuadSubdivideLevel) { | 345 if (level > kMaxQuadSubdivideLevel) { |
| 346 level = kMaxQuadSubdivideLevel; | 346 level = kMaxQuadSubdivideLevel; |
| 347 } | 347 } |
| 348 return level; | 348 return level; |
| 349 } | 349 } |
| 350 | 350 |
| 351 static void hair_path(const SkPath& path, const SkRasterClip& rclip, SkBlitter* blitter, | 351 /* Extend the points in the direction of the starting or ending tangent by 1/2 u nit to |
| 352 account for a round or square cap. If there's no distance between the end poi nt and | |
| 353 the control point, use the next control point to create a tangent. If the cur ve | |
| 354 is degenerate, move the cap out 1/2 unit horizontally. */ | |
| 355 template <SkPaint::Cap capStyle> | |
| 356 void extend_pts(SkPath::Verb prevVerb, SkPath::Verb nextVerb, SkPoint* pts, int ptCount) { | |
| 357 const SkScalar capOutset = SkPaint::kSquare_Cap == capStyle ? 0.5f : SK_Scal arPI / 8; | |
|
reed1
2015/12/08 16:59:02
1. assert that the capStyle is either Square or Ro
caryclark
2015/12/08 19:59:39
Done.
| |
| 358 if (SkPath::kMove_Verb == prevVerb) { | |
| 359 SkPoint* first = pts; | |
| 360 SkPoint* ctrl = first; | |
| 361 int controls = ptCount - 1; | |
| 362 SkVector tangent; | |
| 363 do { | |
| 364 tangent = *first - *++ctrl; | |
| 365 } while (tangent.isZero() && --controls > 0); | |
| 366 if (tangent.isZero()) { | |
| 367 tangent.set(1, 0); | |
| 368 } else { | |
| 369 tangent.normalize(); | |
| 370 } | |
| 371 first->fX += tangent.fX * capOutset; | |
| 372 first->fY += tangent.fY * capOutset; | |
| 373 } | |
| 374 if (SkPath::kMove_Verb == nextVerb || SkPath::kDone_Verb == nextVerb) { | |
| 375 SkPoint* last = &pts[ptCount - 1]; | |
| 376 SkPoint* ctrl = last; | |
| 377 int controls = ptCount - 1; | |
| 378 SkVector tangent; | |
| 379 do { | |
| 380 tangent = *last - *--ctrl; | |
| 381 } while (tangent.isZero() && --controls > 0); | |
| 382 if (tangent.isZero()) { | |
| 383 tangent.set(-1, 0); | |
| 384 } else { | |
| 385 tangent.normalize(); | |
| 386 } | |
| 387 last->fX += tangent.fX * capOutset; | |
| 388 last->fY += tangent.fY * capOutset; | |
| 389 } | |
| 390 } | |
| 391 | |
| 392 template <SkPaint::Cap capStyle> | |
| 393 void hair_path(const SkPath& path, const SkRasterClip& rclip, SkBlitter* blitter , | |
| 352 SkScan::HairRgnProc lineproc) { | 394 SkScan::HairRgnProc lineproc) { |
| 353 if (path.isEmpty()) { | 395 if (path.isEmpty()) { |
| 354 return; | 396 return; |
| 355 } | 397 } |
| 356 | 398 |
| 357 SkAAClipBlitterWrapper wrap; | 399 SkAAClipBlitterWrapper wrap; |
| 358 const SkRegion* clip = nullptr; | 400 const SkRegion* clip = nullptr; |
| 359 | 401 |
| 360 { | 402 { |
| 361 const SkIRect ibounds = path.getBounds().roundOut().makeOutset(1, 1); | 403 const SkIRect ibounds = path.getBounds().roundOut().makeOutset(1, 1); |
| 362 | 404 |
| 363 if (rclip.quickReject(ibounds)) { | 405 if (rclip.quickReject(ibounds)) { |
| 364 return; | 406 return; |
| 365 } | 407 } |
| 366 if (!rclip.quickContains(ibounds)) { | 408 if (!rclip.quickContains(ibounds)) { |
| 367 if (rclip.isBW()) { | 409 if (rclip.isBW()) { |
| 368 clip = &rclip.bwRgn(); | 410 clip = &rclip.bwRgn(); |
| 369 } else { | 411 } else { |
| 370 wrap.init(rclip, blitter); | 412 wrap.init(rclip, blitter); |
| 371 blitter = wrap.getBlitter(); | 413 blitter = wrap.getBlitter(); |
| 372 clip = &wrap.getRgn(); | 414 clip = &wrap.getRgn(); |
| 373 } | 415 } |
| 374 } | 416 } |
| 375 } | 417 } |
| 376 | 418 |
| 377 SkPath::RawIter iter(path); | 419 SkPath::RawIter iter(path); |
| 378 SkPoint pts[4], firstPt, lastPt; | 420 SkPoint pts[4], firstPt, lastPt; |
| 379 SkPath::Verb verb; | 421 SkPath::Verb verb, prevVerb; |
| 380 SkAutoConicToQuads converter; | 422 SkAutoConicToQuads converter; |
| 381 | 423 |
| 424 if (SkPaint::kButt_Cap != capStyle) { | |
| 425 prevVerb = SkPath::kDone_Verb; | |
| 426 } | |
| 382 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { | 427 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { |
| 383 switch (verb) { | 428 switch (verb) { |
| 384 case SkPath::kMove_Verb: | 429 case SkPath::kMove_Verb: |
| 385 firstPt = lastPt = pts[0]; | 430 firstPt = lastPt = pts[0]; |
| 386 break; | 431 break; |
| 387 case SkPath::kLine_Verb: | 432 case SkPath::kLine_Verb: |
| 433 if (SkPaint::kButt_Cap != capStyle) { | |
| 434 extend_pts<capStyle>(prevVerb, iter.peek(), pts, 2); | |
| 435 } | |
| 388 lineproc(pts, 2, clip, blitter); | 436 lineproc(pts, 2, clip, blitter); |
| 389 lastPt = pts[1]; | 437 lastPt = pts[1]; |
| 390 break; | 438 break; |
| 391 case SkPath::kQuad_Verb: | 439 case SkPath::kQuad_Verb: |
| 440 if (SkPaint::kButt_Cap != capStyle) { | |
| 441 extend_pts<capStyle>(prevVerb, iter.peek(), pts, 3); | |
| 442 } | |
| 392 hairquad(pts, clip, blitter, compute_quad_level(pts), lineproc); | 443 hairquad(pts, clip, blitter, compute_quad_level(pts), lineproc); |
| 393 lastPt = pts[2]; | 444 lastPt = pts[2]; |
| 394 break; | 445 break; |
| 395 case SkPath::kConic_Verb: { | 446 case SkPath::kConic_Verb: { |
| 447 if (SkPaint::kButt_Cap != capStyle) { | |
| 448 extend_pts<capStyle>(prevVerb, iter.peek(), pts, 3); | |
| 449 } | |
| 396 // how close should the quads be to the original conic? | 450 // how close should the quads be to the original conic? |
| 397 const SkScalar tol = SK_Scalar1 / 4; | 451 const SkScalar tol = SK_Scalar1 / 4; |
| 398 const SkPoint* quadPts = converter.computeQuads(pts, | 452 const SkPoint* quadPts = converter.computeQuads(pts, |
| 399 iter.conicWeight(), tol); | 453 iter.conicWeight(), tol); |
| 400 for (int i = 0; i < converter.countQuads(); ++i) { | 454 for (int i = 0; i < converter.countQuads(); ++i) { |
| 401 int level = compute_quad_level(quadPts); | 455 int level = compute_quad_level(quadPts); |
| 402 hairquad(quadPts, clip, blitter, level, lineproc); | 456 hairquad(quadPts, clip, blitter, level, lineproc); |
| 403 quadPts += 2; | 457 quadPts += 2; |
| 404 } | 458 } |
| 405 lastPt = pts[2]; | 459 lastPt = pts[2]; |
| 406 break; | 460 break; |
| 407 } | 461 } |
| 408 case SkPath::kCubic_Verb: { | 462 case SkPath::kCubic_Verb: { |
| 463 if (SkPaint::kButt_Cap != capStyle) { | |
| 464 extend_pts<capStyle>(prevVerb, iter.peek(), pts, 4); | |
| 465 } | |
| 409 haircubic(pts, clip, blitter, kMaxCubicSubdivideLevel, lineproc) ; | 466 haircubic(pts, clip, blitter, kMaxCubicSubdivideLevel, lineproc) ; |
| 410 lastPt = pts[3]; | 467 lastPt = pts[3]; |
| 411 } break; | 468 } break; |
| 412 case SkPath::kClose_Verb: | 469 case SkPath::kClose_Verb: |
| 413 pts[0] = lastPt; | 470 pts[0] = lastPt; |
| 414 pts[1] = firstPt; | 471 pts[1] = firstPt; |
| 415 lineproc(pts, 2, clip, blitter); | 472 lineproc(pts, 2, clip, blitter); |
| 416 break; | 473 break; |
| 417 case SkPath::kDone_Verb: | 474 case SkPath::kDone_Verb: |
| 418 break; | 475 break; |
| 419 } | 476 } |
| 477 if (SkPaint::kButt_Cap != capStyle) { | |
| 478 prevVerb = verb; | |
| 479 } | |
| 420 } | 480 } |
| 421 } | 481 } |
| 422 | 482 |
| 423 void SkScan::HairPath(const SkPath& path, const SkRasterClip& clip, SkBlitter* b litter) { | 483 void SkScan::HairPath(const SkPath& path, const SkRasterClip& clip, SkBlitter* b litter) { |
| 424 hair_path(path, clip, blitter, SkScan::HairLineRgn); | 484 hair_path<SkPaint::kButt_Cap>(path, clip, blitter, SkScan::HairLineRgn); |
| 425 } | 485 } |
| 426 | 486 |
| 427 void SkScan::AntiHairPath(const SkPath& path, const SkRasterClip& clip, SkBlitte r* blitter) { | 487 void SkScan::AntiHairPath(const SkPath& path, const SkRasterClip& clip, SkBlitte r* blitter) { |
| 428 hair_path(path, clip, blitter, SkScan::AntiHairLineRgn); | 488 hair_path<SkPaint::kButt_Cap>(path, clip, blitter, SkScan::AntiHairLineRgn); |
| 489 } | |
| 490 | |
| 491 void SkScan::HairSquarePath(const SkPath& path, const SkRasterClip& clip, SkBlit ter* blitter) { | |
| 492 hair_path<SkPaint::kSquare_Cap>(path, clip, blitter, SkScan::HairLineRgn); | |
| 493 } | |
| 494 | |
| 495 void SkScan::AntiHairSquarePath(const SkPath& path, const SkRasterClip& clip, Sk Blitter* blitter) { | |
| 496 hair_path<SkPaint::kSquare_Cap>(path, clip, blitter, SkScan::AntiHairLineRgn ); | |
| 497 } | |
| 498 | |
| 499 void SkScan::HairRoundPath(const SkPath& path, const SkRasterClip& clip, SkBlitt er* blitter) { | |
| 500 hair_path<SkPaint::kRound_Cap>(path, clip, blitter, SkScan::HairLineRgn); | |
| 501 } | |
| 502 | |
| 503 void SkScan::AntiHairRoundPath(const SkPath& path, const SkRasterClip& clip, SkB litter* blitter) { | |
| 504 hair_path<SkPaint::kRound_Cap>(path, clip, blitter, SkScan::AntiHairLineRgn) ; | |
| 429 } | 505 } |
| 430 | 506 |
| 431 /////////////////////////////////////////////////////////////////////////////// | 507 /////////////////////////////////////////////////////////////////////////////// |
| 432 | 508 |
| 433 void SkScan::FrameRect(const SkRect& r, const SkPoint& strokeSize, | 509 void SkScan::FrameRect(const SkRect& r, const SkPoint& strokeSize, |
| 434 const SkRasterClip& clip, SkBlitter* blitter) { | 510 const SkRasterClip& clip, SkBlitter* blitter) { |
| 435 SkASSERT(strokeSize.fX >= 0 && strokeSize.fY >= 0); | 511 SkASSERT(strokeSize.fX >= 0 && strokeSize.fY >= 0); |
| 436 | 512 |
| 437 if (strokeSize.fX < 0 || strokeSize.fY < 0) { | 513 if (strokeSize.fX < 0 || strokeSize.fY < 0) { |
| 438 return; | 514 return; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 498 | 574 |
| 499 SkAAClipBlitterWrapper wrap; | 575 SkAAClipBlitterWrapper wrap; |
| 500 if (!clip.quickContains(r.roundOut().makeOutset(1, 1))) { | 576 if (!clip.quickContains(r.roundOut().makeOutset(1, 1))) { |
| 501 wrap.init(clip, blitter); | 577 wrap.init(clip, blitter); |
| 502 blitter = wrap.getBlitter(); | 578 blitter = wrap.getBlitter(); |
| 503 clipRgn = &wrap.getRgn(); | 579 clipRgn = &wrap.getRgn(); |
| 504 } | 580 } |
| 505 AntiHairLineRgn(pts, count, clipRgn, blitter); | 581 AntiHairLineRgn(pts, count, clipRgn, blitter); |
| 506 } | 582 } |
| 507 } | 583 } |
| OLD | NEW |