diff options
author | tomhudson@google.com <tomhudson@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-04-12 14:23:58 +0000 |
---|---|---|
committer | tomhudson@google.com <tomhudson@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-04-12 14:23:58 +0000 |
commit | 17b6ba41f2144cd3ff446d52da9df23ca7d77b90 (patch) | |
tree | 6fcebb82ae0fbeb520b6ed4dd24a3cb719a78623 /src | |
parent | fc9a3be3d2b97aba6aad27e0b9a9f105f08287b9 (diff) |
Reinstate early out from antialiased path rendering if we anticipate
overflow (or if the path is completely clipped out).
Fixes http://code.google.com/p/chromium/issues/detail?id=121405
Reviewed at http://codereview.appspot.com/5989070/
git-svn-id: http://skia.googlecode.com/svn/trunk@3658 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkScan_AntiPath.cpp | 47 |
1 files changed, 44 insertions, 3 deletions
diff --git a/src/core/SkScan_AntiPath.cpp b/src/core/SkScan_AntiPath.cpp index e224ea1052..95c773d25a 100644 --- a/src/core/SkScan_AntiPath.cpp +++ b/src/core/SkScan_AntiPath.cpp @@ -581,6 +581,29 @@ static bool fitsInsideLimit(const SkRect& r, SkScalar max) { r.fRight < max && r.fBottom < max; } +static int overflows_short_shift(int value, int shift) { + const int s = 16 + shift; + return (value << s >> s) - value; +} + +/** + Would any of the coordinates of this rectangle not fit in a short, + when left-shifted by shift? +*/ +static int rect_overflows_short_shift(SkIRect rect, int shift) { + SkASSERT(!overflows_short_shift(8191, SHIFT)); + SkASSERT(overflows_short_shift(8192, SHIFT)); + SkASSERT(!overflows_short_shift(32767, 0)); + SkASSERT(overflows_short_shift(32768, 0)); + + // Since we expect these to succeed, we bit-or together + // for a tiny extra bit of speed. + return overflows_short_shift(rect.fLeft, SHIFT) | + overflows_short_shift(rect.fRight, SHIFT) | + overflows_short_shift(rect.fTop, SHIFT) | + overflows_short_shift(rect.fBottom, SHIFT); +} + static bool safeRoundOut(const SkRect& src, SkIRect* dst, int32_t maxInt) { #ifdef SK_SCALAR_IS_FIXED // the max-int (shifted) is exactly what we want to compare against, to know @@ -618,12 +641,30 @@ void SkScan::AntiFillPath(const SkPath& path, const SkRegion& origClip, return; } + // If the intersection of the path bounds and the clip bounds + // will overflow 32767 when << by SHIFT, we can't supersample, + // so draw without antialiasing. + SkIRect clippedIR; + if (path.isInverseFillType()) { + // If the path is an inverse fill, it's going to fill the entire + // clip, and we care whether the entire clip exceeds our limits. + clippedIR = origClip.getBounds(); + } else { + if (!clippedIR.intersect(ir, origClip.getBounds())) { + return; + } + } + if (rect_overflows_short_shift(clippedIR, SHIFT)) { + SkScan::FillPath(path, origClip, blitter); + return; + } + // Our antialiasing can't handle a clip larger than 32767, so we restrict // the clip to that limit here. (the runs[] uses int16_t for its index). // - // A more general solution (one that could also eliminate the need to disable - // aa based on ir bounds (see overflows_short_shift) would be to tile the - // clip/target... + // A more general solution (one that could also eliminate the need to + // disable aa based on ir bounds (see overflows_short_shift) would be + // to tile the clip/target... SkRegion tmpClipStorage; const SkRegion* clipRgn = &origClip; { |