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 "SkScanPriv.h" | 8 #include "SkScanPriv.h" |
9 #include "SkBlitter.h" | 9 #include "SkBlitter.h" |
10 #include "SkEdge.h" | 10 #include "SkEdge.h" |
(...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
552 | 552 |
553 SkIRect limitR; | 553 SkIRect limitR; |
554 limitR.set(-limit, -limit, limit, limit); | 554 limitR.set(-limit, -limit, limit, limit); |
555 if (limitR.contains(orig.getBounds())) { | 555 if (limitR.contains(orig.getBounds())) { |
556 return false; | 556 return false; |
557 } | 557 } |
558 reduced->op(orig, limitR, SkRegion::kIntersect_Op); | 558 reduced->op(orig, limitR, SkRegion::kIntersect_Op); |
559 return true; | 559 return true; |
560 } | 560 } |
561 | 561 |
| 562 /** |
| 563 * Variant of SkScalarRoundToInt, identical to SkDScalarRoundToInt except when
the input fraction |
| 564 * is 0.5. In this case only, round the value down. This is used to round the t
op and left |
| 565 * of a rectangle, and corresponds to the way the scan converter treats the top
and left edges. |
| 566 */ |
| 567 static inline int round_down_to_int(SkScalar x) { |
| 568 double xx = x; |
| 569 xx += 0.5; |
| 570 double floorXX = floor(xx); |
| 571 return (int)floorXX - (xx == floorXX); |
| 572 } |
| 573 |
| 574 /** |
| 575 * Variant of SkRect::round() that explicitly performs the rounding step (i.e.
floor(x + 0.5)) |
| 576 * using double instead of SkScalar (float). It does this by calling SkDScalar
RoundToInt(), |
| 577 * which may be slower than calling SkScalarRountToInt(), but gives slightly m
ore accurate |
| 578 * results. Also rounds top and left using double, flooring when the fraction
is exactly 0.5f. |
| 579 * |
| 580 * e.g. |
| 581 * SkScalar left = 0.5f; |
| 582 * int ileft = SkScalarRoundToInt(left); |
| 583 * SkASSERT(0 == ileft); // <--- fails |
| 584 * int ileft = round_down_to_int(left); |
| 585 * SkASSERT(0 == ileft); // <--- succeeds |
| 586 * SkScalar right = 0.49999997f; |
| 587 * int iright = SkScalarRoundToInt(right); |
| 588 * SkASSERT(0 == iright); // <--- fails |
| 589 * iright = SkDScalarRoundToInt(right); |
| 590 * SkASSERT(0 == iright); // <--- succeeds |
| 591 */ |
| 592 static void round_asymmetric_to_int(const SkRect& src, SkIRect* dst) { |
| 593 SkASSERT(dst); |
| 594 dst->set(round_down_to_int(src.fLeft), round_down_to_int(src.fTop), |
| 595 SkDScalarRoundToInt(src.fRight), SkDScalarRoundToInt(src.fBottom)); |
| 596 } |
| 597 |
562 void SkScan::FillPath(const SkPath& path, const SkRegion& origClip, | 598 void SkScan::FillPath(const SkPath& path, const SkRegion& origClip, |
563 SkBlitter* blitter) { | 599 SkBlitter* blitter) { |
564 if (origClip.isEmpty()) { | 600 if (origClip.isEmpty()) { |
565 return; | 601 return; |
566 } | 602 } |
567 | 603 |
568 // Our edges are fixed-point, and don't like the bounds of the clip to | 604 // Our edges are fixed-point, and don't like the bounds of the clip to |
569 // exceed that. Here we trim the clip just so we don't overflow later on | 605 // exceed that. Here we trim the clip just so we don't overflow later on |
570 const SkRegion* clipPtr = &origClip; | 606 const SkRegion* clipPtr = &origClip; |
571 SkRegion finiteClip; | 607 SkRegion finiteClip; |
572 if (clip_to_limit(origClip, &finiteClip)) { | 608 if (clip_to_limit(origClip, &finiteClip)) { |
573 if (finiteClip.isEmpty()) { | 609 if (finiteClip.isEmpty()) { |
574 return; | 610 return; |
575 } | 611 } |
576 clipPtr = &finiteClip; | 612 clipPtr = &finiteClip; |
577 } | 613 } |
578 // don't reference "origClip" any more, just use clipPtr | 614 // don't reference "origClip" any more, just use clipPtr |
579 | 615 |
580 SkIRect ir; | 616 SkIRect ir; |
581 // We deliberately call dround() instead of round(), since we can't afford t
o generate a | 617 // We deliberately call round_asymmetric_to_int() instead of round(), since
we can't afford |
582 // bounds that is tighter than the corresponding SkEdges. The edge code basi
cally converts | 618 // to generate a bounds that is tighter than the corresponding SkEdges. The
edge code basically |
583 // the floats to fixed, and then "rounds". If we called round() instead of d
round() here, | 619 // converts the floats to fixed, and then "rounds". If we called round() ins
tead of |
584 // we could generate the wrong ir for values like 0.4999997. | 620 // round_asymmetric_to_int() here, we could generate the wrong ir for values
like 0.4999997. |
585 path.getBounds().dround(&ir); | 621 round_asymmetric_to_int(path.getBounds(), &ir); |
586 if (ir.isEmpty()) { | 622 if (ir.isEmpty()) { |
587 if (path.isInverseFillType()) { | 623 if (path.isInverseFillType()) { |
588 blitter->blitRegion(*clipPtr); | 624 blitter->blitRegion(*clipPtr); |
589 } | 625 } |
590 return; | 626 return; |
591 } | 627 } |
592 | 628 |
593 SkScanClipper clipper(blitter, clipPtr, ir, path.isInverseFillType()); | 629 SkScanClipper clipper(blitter, clipPtr, ir, path.isInverseFillType()); |
594 | 630 |
595 blitter = clipper.getBlitter(); | 631 blitter = clipper.getBlitter(); |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
700 clipRgn = &wrap.getRgn(); | 736 clipRgn = &wrap.getRgn(); |
701 blitter = wrap.getBlitter(); | 737 blitter = wrap.getBlitter(); |
702 } | 738 } |
703 | 739 |
704 SkScanClipper clipper(blitter, clipRgn, ir); | 740 SkScanClipper clipper(blitter, clipRgn, ir); |
705 blitter = clipper.getBlitter(); | 741 blitter = clipper.getBlitter(); |
706 if (blitter) { | 742 if (blitter) { |
707 sk_fill_triangle(pts, clipper.getClipRect(), blitter, ir); | 743 sk_fill_triangle(pts, clipper.getClipRect(), blitter, ir); |
708 } | 744 } |
709 } | 745 } |
OLD | NEW |