| 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 | 8 |
| 9 #include "SkScanPriv.h" | 9 #include "SkScanPriv.h" |
| 10 #include "SkPath.h" | 10 #include "SkPath.h" |
| (...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 576 (1 << (8 - SHIFT)) - (((y & MASK) + 1) >> SHIFT)); | 576 (1 << (8 - SHIFT)) - (((y & MASK) + 1) >> SHIFT)); |
| 577 } | 577 } |
| 578 | 578 |
| 579 #ifdef SK_DEBUG | 579 #ifdef SK_DEBUG |
| 580 fCurrX = x + width; | 580 fCurrX = x + width; |
| 581 #endif | 581 #endif |
| 582 } | 582 } |
| 583 | 583 |
| 584 /////////////////////////////////////////////////////////////////////////////// | 584 /////////////////////////////////////////////////////////////////////////////// |
| 585 | 585 |
| 586 static bool fitsInsideLimit(const SkRect& r, SkScalar max) { | |
| 587 const SkScalar min = -max; | |
| 588 return r.fLeft > min && r.fTop > min && | |
| 589 r.fRight < max && r.fBottom < max; | |
| 590 } | |
| 591 | |
| 592 static int overflows_short_shift(int value, int shift) { | 586 static int overflows_short_shift(int value, int shift) { |
| 593 const int s = 16 + shift; | 587 const int s = 16 + shift; |
| 594 return (SkLeftShift(value, s) >> s) - value; | 588 return (SkLeftShift(value, s) >> s) - value; |
| 595 } | 589 } |
| 596 | 590 |
| 597 /** | 591 /** |
| 598 Would any of the coordinates of this rectangle not fit in a short, | 592 Would any of the coordinates of this rectangle not fit in a short, |
| 599 when left-shifted by shift? | 593 when left-shifted by shift? |
| 600 */ | 594 */ |
| 601 static int rect_overflows_short_shift(SkIRect rect, int shift) { | 595 static int rect_overflows_short_shift(SkIRect rect) { |
| 602 SkASSERT(!overflows_short_shift(8191, SHIFT)); | 596 SkASSERT(!overflows_short_shift(8191, SHIFT)); |
| 603 SkASSERT(overflows_short_shift(8192, SHIFT)); | 597 SkASSERT(overflows_short_shift(8192, SHIFT)); |
| 604 SkASSERT(!overflows_short_shift(32767, 0)); | 598 SkASSERT(!overflows_short_shift(32767, 0)); |
| 605 SkASSERT(overflows_short_shift(32768, 0)); | 599 SkASSERT(overflows_short_shift(32768, 0)); |
| 606 | 600 |
| 607 // Since we expect these to succeed, we bit-or together | 601 // Since we expect these to succeed, we bit-or together |
| 608 // for a tiny extra bit of speed. | 602 // for a tiny extra bit of speed. |
| 609 return overflows_short_shift(rect.fLeft, SHIFT) | | 603 return overflows_short_shift(rect.fLeft, SHIFT) | |
| 610 overflows_short_shift(rect.fRight, SHIFT) | | 604 overflows_short_shift(rect.fRight, SHIFT) | |
| 611 overflows_short_shift(rect.fTop, SHIFT) | | 605 overflows_short_shift(rect.fTop, SHIFT) | |
| 612 overflows_short_shift(rect.fBottom, SHIFT); | 606 overflows_short_shift(rect.fBottom, SHIFT); |
| 613 } | 607 } |
| 614 | 608 |
| 615 static bool safeRoundOut(const SkRect& src, SkIRect* dst, int32_t maxInt) { | 609 // When src has huge coordinates, clips dst by clip and returns true. |
| 616 const SkScalar maxScalar = SkIntToScalar(maxInt); | 610 static bool roundOutClipped(const SkRect& src, const SkIRect& clip, SkIRect* dst
) { |
| 617 | 611 static const int32_t kLimit = (SK_MaxS32 >> SHIFT) - 1; |
| 618 if (fitsInsideLimit(src, maxScalar)) { | 612 const SkIRect max = SkIRect::MakeLTRB(-kLimit, -kLimit, kLimit, kLimit); |
| 613 if (max.contains(src)) { |
| 619 src.roundOut(dst); | 614 src.roundOut(dst); |
| 620 return true; | 615 return false; |
| 621 } | 616 } |
| 622 return false; | 617 SkRect clipped; |
| 618 if (clipped.intersect(src, SkRect::Make(clip))) { |
| 619 clipped.roundOut(dst); |
| 620 } else { |
| 621 dst->setEmpty(); |
| 622 } |
| 623 return true; |
| 623 } | 624 } |
| 624 | 625 |
| 625 void SkScan::AntiFillPath(const SkPath& path, const SkRegion& origClip, | 626 void SkScan::AntiFillPath(const SkPath& path, const SkRegion& origClip, |
| 626 SkBlitter* blitter, bool forceRLE) { | 627 SkBlitter* blitter, bool forceRLE) { |
| 627 if (origClip.isEmpty()) { | 628 if (origClip.isEmpty()) { |
| 628 return; | 629 return; |
| 629 } | 630 } |
| 630 | 631 |
| 631 const bool isInverse = path.isInverseFillType(); | 632 const bool isInverse = path.isInverseFillType(); |
| 632 SkIRect ir; | 633 SkIRect ir; |
| 633 | 634 |
| 634 if (!safeRoundOut(path.getBounds(), &ir, SK_MaxS32 >> SHIFT)) { | 635 bool irIsClipped = roundOutClipped(path.getBounds(), origClip.getBounds(), &
ir); |
| 635 #if 0 | |
| 636 const SkRect& r = path.getBounds(); | |
| 637 SkDebugf("--- bounds can't fit in SkIRect\n", r.fLeft, r.fTop, r.fRight,
r.fBottom); | |
| 638 #endif | |
| 639 return; | |
| 640 } | |
| 641 if (ir.isEmpty()) { | 636 if (ir.isEmpty()) { |
| 642 if (isInverse) { | 637 if (isInverse) { |
| 643 blitter->blitRegion(origClip); | 638 blitter->blitRegion(origClip); |
| 644 } | 639 } |
| 645 return; | 640 return; |
| 646 } | 641 } |
| 647 | 642 |
| 648 // If the intersection of the path bounds and the clip bounds | 643 // If the intersection of the path bounds and the clip bounds |
| 649 // will overflow 32767 when << by SHIFT, we can't supersample, | 644 // will overflow 32767 when << by SHIFT, we can't supersample, |
| 650 // so draw without antialiasing. | 645 // so draw without antialiasing. |
| 651 SkIRect clippedIR; | 646 SkIRect clippedIR; |
| 652 if (isInverse) { | 647 if (isInverse) { |
| 653 // If the path is an inverse fill, it's going to fill the entire | 648 // If the path is an inverse fill, it's going to fill the entire |
| 654 // clip, and we care whether the entire clip exceeds our limits. | 649 // clip, and we care whether the entire clip exceeds our limits. |
| 655 clippedIR = origClip.getBounds(); | 650 clippedIR = origClip.getBounds(); |
| 656 } else { | 651 } else { |
| 657 if (!clippedIR.intersect(ir, origClip.getBounds())) { | 652 if (!clippedIR.intersect(ir, origClip.getBounds())) { |
| 658 return; | 653 return; |
| 659 } | 654 } |
| 660 } | 655 } |
| 661 if (rect_overflows_short_shift(clippedIR, SHIFT)) { | 656 if (rect_overflows_short_shift(clippedIR)) { |
| 662 SkScan::FillPath(path, origClip, blitter); | 657 SkScan::FillPath(path, origClip, blitter); |
| 663 return; | 658 return; |
| 664 } | 659 } |
| 665 | 660 |
| 666 // Our antialiasing can't handle a clip larger than 32767, so we restrict | 661 // Our antialiasing can't handle a clip larger than 32767, so we restrict |
| 667 // the clip to that limit here. (the runs[] uses int16_t for its index). | 662 // the clip to that limit here. (the runs[] uses int16_t for its index). |
| 668 // | 663 // |
| 669 // A more general solution (one that could also eliminate the need to | 664 // A more general solution (one that could also eliminate the need to |
| 670 // disable aa based on ir bounds (see overflows_short_shift) would be | 665 // disable aa based on ir bounds (see overflows_short_shift) would be |
| 671 // to tile the clip/target... | 666 // to tile the clip/target... |
| 672 SkRegion tmpClipStorage; | 667 SkRegion tmpClipStorage; |
| 673 const SkRegion* clipRgn = &origClip; | 668 const SkRegion* clipRgn = &origClip; |
| 674 { | 669 { |
| 675 static const int32_t kMaxClipCoord = 32767; | 670 static const int32_t kMaxClipCoord = 32767; |
| 676 const SkIRect& bounds = origClip.getBounds(); | 671 const SkIRect& bounds = origClip.getBounds(); |
| 677 if (bounds.fRight > kMaxClipCoord || bounds.fBottom > kMaxClipCoord) { | 672 if (bounds.fRight > kMaxClipCoord || bounds.fBottom > kMaxClipCoord) { |
| 678 SkIRect limit = { 0, 0, kMaxClipCoord, kMaxClipCoord }; | 673 SkIRect limit = { 0, 0, kMaxClipCoord, kMaxClipCoord }; |
| 679 tmpClipStorage.op(origClip, limit, SkRegion::kIntersect_Op); | 674 tmpClipStorage.op(origClip, limit, SkRegion::kIntersect_Op); |
| 680 clipRgn = &tmpClipStorage; | 675 clipRgn = &tmpClipStorage; |
| 681 } | 676 } |
| 682 } | 677 } |
| 683 // for here down, use clipRgn, not origClip | 678 // for here down, use clipRgn, not origClip |
| 684 | 679 |
| 685 SkScanClipper clipper(blitter, clipRgn, ir); | 680 SkScanClipper clipper(blitter, clipRgn, ir, /* skipRejectTest */ false, ir
IsClipped); |
| 686 const SkIRect* clipRect = clipper.getClipRect(); | 681 const SkIRect* clipRect = clipper.getClipRect(); |
| 687 | 682 |
| 688 if (clipper.getBlitter() == nullptr) { // clipped out | 683 if (clipper.getBlitter() == nullptr) { // clipped out |
| 689 if (isInverse) { | 684 if (isInverse) { |
| 690 blitter->blitRegion(*clipRgn); | 685 blitter->blitRegion(*clipRgn); |
| 691 } | 686 } |
| 692 return; | 687 return; |
| 693 } | 688 } |
| 694 | 689 |
| 695 // now use the (possibly wrapped) blitter | 690 // now use the (possibly wrapped) blitter |
| 696 blitter = clipper.getBlitter(); | 691 blitter = clipper.getBlitter(); |
| 697 | 692 |
| 698 if (isInverse) { | 693 if (isInverse) { |
| 699 sk_blit_above(blitter, ir, *clipRgn); | 694 sk_blit_above(blitter, ir, *clipRgn); |
| 700 } | 695 } |
| 701 | 696 |
| 702 SkIRect superRect, *superClipRect = nullptr; | 697 SkIRect superRect, *superClipRect = nullptr; |
| 703 | 698 |
| 704 if (clipRect) { | 699 if (clipRect) { |
| 705 superRect.set(SkLeftShift(clipRect->fLeft, SHIFT), | 700 superRect.set(SkLeftShift(clipRect->fLeft, SHIFT), |
| 706 SkLeftShift(clipRect->fTop, SHIFT), | 701 SkLeftShift(clipRect->fTop, SHIFT), |
| 707 SkLeftShift(clipRect->fRight, SHIFT), | 702 SkLeftShift(clipRect->fRight, SHIFT), |
| 708 SkLeftShift(clipRect->fBottom, SHIFT)); | 703 SkLeftShift(clipRect->fBottom, SHIFT)); |
| 709 superClipRect = &superRect; | 704 superClipRect = &superRect; |
| 710 } | 705 } |
| 711 | 706 |
| 712 SkASSERT(SkIntToScalar(ir.fTop) <= path.getBounds().fTop); | |
| 713 | |
| 714 // MaskSuperBlitter can't handle drawing outside of ir, so we can't use it | 707 // MaskSuperBlitter can't handle drawing outside of ir, so we can't use it |
| 715 // if we're an inverse filltype | 708 // if we're an inverse filltype |
| 716 if (!isInverse && MaskSuperBlitter::CanHandleRect(ir) && !forceRLE) { | 709 if (!isInverse && !irIsClipped && MaskSuperBlitter::CanHandleRect(ir) && !fo
rceRLE) { |
| 717 MaskSuperBlitter superBlit(blitter, ir, *clipRgn, isInverse); | 710 MaskSuperBlitter superBlit(blitter, ir, *clipRgn, isInverse); |
| 718 SkASSERT(SkIntToScalar(ir.fTop) <= path.getBounds().fTop); | 711 SkASSERT(SkIntToScalar(ir.fTop) <= path.getBounds().fTop); |
| 719 sk_fill_path(path, superClipRect, &superBlit, ir.fTop, ir.fBottom, SHIFT
, *clipRgn); | 712 sk_fill_path(path, superClipRect, &superBlit, ir.fTop, ir.fBottom, SHIFT
, *clipRgn); |
| 720 } else { | 713 } else { |
| 721 SuperBlitter superBlit(blitter, ir, *clipRgn, isInverse); | 714 SuperBlitter superBlit(blitter, ir, *clipRgn, isInverse); |
| 722 sk_fill_path(path, superClipRect, &superBlit, ir.fTop, ir.fBottom, SHIFT
, *clipRgn); | 715 sk_fill_path(path, superClipRect, &superBlit, ir.fTop, ir.fBottom, SHIFT
, *clipRgn); |
| 723 } | 716 } |
| 724 | 717 |
| 725 if (isInverse) { | 718 if (isInverse) { |
| 726 sk_blit_below(blitter, ir, *clipRgn); | 719 sk_blit_below(blitter, ir, *clipRgn); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 759 AntiFillPath(path, clip.bwRgn(), blitter); | 752 AntiFillPath(path, clip.bwRgn(), blitter); |
| 760 } else { | 753 } else { |
| 761 SkRegion tmp; | 754 SkRegion tmp; |
| 762 SkAAClipBlitter aaBlitter; | 755 SkAAClipBlitter aaBlitter; |
| 763 | 756 |
| 764 tmp.setRect(clip.getBounds()); | 757 tmp.setRect(clip.getBounds()); |
| 765 aaBlitter.init(blitter, &clip.aaRgn()); | 758 aaBlitter.init(blitter, &clip.aaRgn()); |
| 766 SkScan::AntiFillPath(path, tmp, &aaBlitter, true); | 759 SkScan::AntiFillPath(path, tmp, &aaBlitter, true); |
| 767 } | 760 } |
| 768 } | 761 } |
| OLD | NEW |