Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(435)

Side by Side Diff: src/core/SkScan_Path.cpp

Issue 1893433002: In SkDraw::drawRect, use SkPath for huge rects. Base URL: https://skia.googlesource.com/skia@fixed-assert
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/core/SkScan_Hairline.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "SkScanPriv.h" 8 #include "SkScanPriv.h"
9 #include "SkBlitter.h" 9 #include "SkBlitter.h"
10 #include "SkEdge.h" 10 #include "SkEdge.h"
(...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 tmp.fBottom = cr.fBottom; 538 tmp.fBottom = cr.fBottom;
539 if (!tmp.isEmpty()) { 539 if (!tmp.isEmpty()) {
540 blitter->blitRectRegion(tmp, clip); 540 blitter->blitRectRegion(tmp, clip);
541 } 541 }
542 } 542 }
543 543
544 /////////////////////////////////////////////////////////////////////////////// 544 ///////////////////////////////////////////////////////////////////////////////
545 545
546 /** 546 /**
547 * If the caller is drawing an inverse-fill path, then it pass true for 547 * If the caller is drawing an inverse-fill path, then it pass true for
548 * skipRejectTest, so we don't abort drawing just because the src bounds (ir) 548 * skipRejectTest, so we don't abort drawing just because the src bounds
549 * is outside of the clip. 549 * is outside of the clip.
550 */ 550 */
551 SkScanClipper::SkScanClipper(SkBlitter* blitter, const SkRegion* clip, 551 SkScanClipper::SkScanClipper(SkBlitter* blitter, const SkRegion* clip,
552 const SkIRect& ir, bool skipRejectTest) { 552 const SkIRect& bounds, bool skipRejectTest, bool bo undsIsTruncated) {
553 fBlitter = nullptr; // null means blit nothing 553 fBlitter = nullptr; // null means blit nothing
554 fClipRect = nullptr; 554 fClipRect = nullptr;
555 555
556 if (clip) { 556 if (clip) {
557 fClipRect = &clip->getBounds(); 557 fClipRect = &clip->getBounds();
558 if (!skipRejectTest && !SkIRect::Intersects(*fClipRect, ir)) { // comple tely clipped out 558 if (!skipRejectTest && !SkIRect::Intersects(*fClipRect, bounds)) { // co mpletely clipped out
559 return; 559 return;
560 } 560 }
561 561
562 if (clip->isRect()) { 562 if (clip->isRect()) {
563 if (fClipRect->contains(ir)) { 563 if (!boundsIsTruncated && fClipRect->contains(bounds)) {
564 fClipRect = nullptr; 564 fClipRect = nullptr;
565 } else { 565 } else {
566 // only need a wrapper blitter if we're horizontally clipped 566 // only need a wrapper blitter if we're horizontally clipped
567 if (fClipRect->fLeft > ir.fLeft || fClipRect->fRight < ir.fRight ) { 567 if (boundsIsTruncated ||
568 fClipRect->fLeft > bounds.fLeft || fClipRect->fRight < bound s.fRight) {
568 fRectBlitter.init(blitter, *fClipRect); 569 fRectBlitter.init(blitter, *fClipRect);
569 blitter = &fRectBlitter; 570 blitter = &fRectBlitter;
570 } 571 }
571 } 572 }
572 } else { 573 } else {
573 fRgnBlitter.init(blitter, clip); 574 fRgnBlitter.init(blitter, clip);
574 blitter = &fRgnBlitter; 575 blitter = &fRgnBlitter;
575 } 576 }
576 } 577 }
577 fBlitter = blitter; 578 fBlitter = blitter;
(...skipping 24 matching lines...) Expand all
602 double floorXX = floor(xx); 603 double floorXX = floor(xx);
603 return (int)floorXX - (xx == floorXX); 604 return (int)floorXX - (xx == floorXX);
604 } 605 }
605 606
606 /** 607 /**
607 * Variant of SkRect::round() that explicitly performs the rounding step (i.e. floor(x + 0.5)) 608 * Variant of SkRect::round() that explicitly performs the rounding step (i.e. floor(x + 0.5))
608 * using double instead of SkScalar (float). It does this by calling SkDScalar RoundToInt(), 609 * using double instead of SkScalar (float). It does this by calling SkDScalar RoundToInt(),
609 * which may be slower than calling SkScalarRountToInt(), but gives slightly m ore accurate 610 * which may be slower than calling SkScalarRountToInt(), but gives slightly m ore accurate
610 * results. Also rounds top and left using double, flooring when the fraction is exactly 0.5f. 611 * results. Also rounds top and left using double, flooring when the fraction is exactly 0.5f.
611 * 612 *
613 * When src has huge coordinates, clips dst by clip and returns true.
614 *
612 * e.g. 615 * e.g.
613 * SkScalar left = 0.5f; 616 * SkScalar left = 0.5f;
614 * int ileft = SkScalarRoundToInt(left); 617 * int ileft = SkScalarRoundToInt(left);
615 * SkASSERT(0 == ileft); // <--- fails 618 * SkASSERT(0 == ileft); // <--- fails
616 * int ileft = round_down_to_int(left); 619 * int ileft = round_down_to_int(left);
617 * SkASSERT(0 == ileft); // <--- succeeds 620 * SkASSERT(0 == ileft); // <--- succeeds
618 * SkScalar right = 0.49999997f; 621 * SkScalar right = 0.49999997f;
619 * int iright = SkScalarRoundToInt(right); 622 * int iright = SkScalarRoundToInt(right);
620 * SkASSERT(0 == iright); // <--- fails 623 * SkASSERT(0 == iright); // <--- fails
621 * iright = SkDScalarRoundToInt(right); 624 * iright = SkDScalarRoundToInt(right);
622 * SkASSERT(0 == iright); // <--- succeeds 625 * SkASSERT(0 == iright); // <--- succeeds
623 */ 626 */
624 static void round_asymmetric_to_int(const SkRect& src, SkIRect* dst) { 627 static bool round_asymmetric_to_int(const SkRect& src, const SkIRect& clip, SkIR ect* dst) {
625 SkASSERT(dst); 628 SkASSERT(dst);
626 dst->set(round_down_to_int(src.fLeft), round_down_to_int(src.fTop), 629 static const int32_t kLimit = 32767;
627 SkDScalarRoundToInt(src.fRight), SkDScalarRoundToInt(src.fBottom)); 630 const SkIRect max = SkIRect::MakeLTRB(-kLimit, -kLimit, kLimit, kLimit);
631 if (max.contains(src)) {
632 dst->set(round_down_to_int(src.fLeft), round_down_to_int(src.fTop),
633 SkDScalarRoundToInt(src.fRight), SkDScalarRoundToInt(src.fBotto m));
634 return false;
635 }
636 SkRect clipped;
637 if (clipped.intersect(src, SkRect::Make(clip))) {
638 dst->set(round_down_to_int(clipped.fLeft), round_down_to_int(clipped.fTo p),
639 SkDScalarRoundToInt(clipped.fRight), SkDScalarRoundToInt(clippe d.fBottom));
640 } else {
641 dst->setEmpty();
642 }
643 return true;
628 } 644 }
629 645
630 void SkScan::FillPath(const SkPath& path, const SkRegion& origClip, 646 void SkScan::FillPath(const SkPath& path, const SkRegion& origClip,
631 SkBlitter* blitter) { 647 SkBlitter* blitter) {
632 if (origClip.isEmpty()) { 648 if (origClip.isEmpty()) {
633 return; 649 return;
634 } 650 }
635 651
636 // Our edges are fixed-point, and don't like the bounds of the clip to 652 // Our edges are fixed-point, and don't like the bounds of the clip to
637 // exceed that. Here we trim the clip just so we don't overflow later on 653 // exceed that. Here we trim the clip just so we don't overflow later on
638 const SkRegion* clipPtr = &origClip; 654 const SkRegion* clipPtr = &origClip;
639 SkRegion finiteClip; 655 SkRegion finiteClip;
640 if (clip_to_limit(origClip, &finiteClip)) { 656 if (clip_to_limit(origClip, &finiteClip)) {
641 if (finiteClip.isEmpty()) { 657 if (finiteClip.isEmpty()) {
642 return; 658 return;
643 } 659 }
644 clipPtr = &finiteClip; 660 clipPtr = &finiteClip;
645 } 661 }
646 // don't reference "origClip" any more, just use clipPtr 662 // don't reference "origClip" any more, just use clipPtr
647 663
648 SkIRect ir; 664 SkIRect ir;
649 // We deliberately call round_asymmetric_to_int() instead of round(), since we can't afford 665 // We deliberately call round_asymmetric_to_int() instead of round(), since we can't afford
650 // to generate a bounds that is tighter than the corresponding SkEdges. The edge code basically 666 // to generate a bounds that is tighter than the corresponding SkEdges. The edge code basically
651 // converts the floats to fixed, and then "rounds". If we called round() ins tead of 667 // converts the floats to fixed, and then "rounds". If we called round() ins tead of
652 // round_asymmetric_to_int() here, we could generate the wrong ir for values like 0.4999997. 668 // round_asymmetric_to_int() here, we could generate the wrong ir for values like 0.4999997.
653 round_asymmetric_to_int(path.getBounds(), &ir); 669 bool irIsClipped = round_asymmetric_to_int(path.getBounds(), clipPtr->getBou nds(), &ir);
654 if (ir.isEmpty()) { 670 if (ir.isEmpty()) {
655 if (path.isInverseFillType()) { 671 if (path.isInverseFillType()) {
656 blitter->blitRegion(*clipPtr); 672 blitter->blitRegion(*clipPtr);
657 } 673 }
658 return; 674 return;
659 } 675 }
660 676
661 SkScanClipper clipper(blitter, clipPtr, ir, path.isInverseFillType()); 677 SkScanClipper clipper(blitter, clipPtr, ir, path.isInverseFillType(), irIsCl ipped);
662 678
663 blitter = clipper.getBlitter(); 679 blitter = clipper.getBlitter();
664 if (blitter) { 680 if (blitter) {
665 // we have to keep our calls to blitter in sorted order, so we 681 // we have to keep our calls to blitter in sorted order, so we
666 // must blit the above section first, then the middle, then the bottom. 682 // must blit the above section first, then the middle, then the bottom.
667 if (path.isInverseFillType()) { 683 if (path.isInverseFillType()) {
668 sk_blit_above(blitter, ir, *clipPtr); 684 sk_blit_above(blitter, ir, *clipPtr);
669 } 685 }
670 sk_fill_path(path, clipper.getClipRect(), blitter, ir.fTop, ir.fBottom, 686 sk_fill_path(path, clipper.getClipRect(), blitter, ir.fTop, ir.fBottom,
671 0, *clipPtr); 687 0, *clipPtr);
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
768 clipRgn = &wrap.getRgn(); 784 clipRgn = &wrap.getRgn();
769 blitter = wrap.getBlitter(); 785 blitter = wrap.getBlitter();
770 } 786 }
771 787
772 SkScanClipper clipper(blitter, clipRgn, ir); 788 SkScanClipper clipper(blitter, clipRgn, ir);
773 blitter = clipper.getBlitter(); 789 blitter = clipper.getBlitter();
774 if (blitter) { 790 if (blitter) {
775 sk_fill_triangle(pts, clipper.getClipRect(), blitter, ir); 791 sk_fill_triangle(pts, clipper.getClipRect(), blitter, ir);
776 } 792 }
777 } 793 }
OLDNEW
« no previous file with comments | « src/core/SkScan_Hairline.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698