aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-02-28 15:32:42 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-02-28 15:32:42 +0000
commit07db86126a5bc30d4eaf00e69890e89d4add4370 (patch)
tree1725f146f43f1aae6ba908db20e69c55ed32a847
parent5e5a095a94281167056da707b03930f135748d71 (diff)
since SkScalarCeil/Floor do not explicitly detect overflows from float->int,
create special version of roundOut that checks if the result can fit, and if not we abort the draw. 32bits (or 30 for antialiasing) should be enough for anyone... git-svn-id: http://skia.googlecode.com/svn/trunk@3271 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--src/core/SkScan_AntiPath.cpp42
1 files changed, 21 insertions, 21 deletions
diff --git a/src/core/SkScan_AntiPath.cpp b/src/core/SkScan_AntiPath.cpp
index 261a7f1462..9d05d32bc7 100644
--- a/src/core/SkScan_AntiPath.cpp
+++ b/src/core/SkScan_AntiPath.cpp
@@ -573,13 +573,19 @@ void MaskSuperBlitter::blitH(int x, int y, int width) {
///////////////////////////////////////////////////////////////////////////////
-/* Returns non-zero if (value << shift) overflows a short, which would mean
- we could not shift it up and then convert to SkFixed.
- i.e. is x expressible as signed (16-shift) bits?
- */
-static int overflows_short_shift(int value, int shift) {
- const int s = 16 + shift;
- return (value << s >> s) - value;
+static bool fitsInsideLimit(const SkRect& r, SkScalar max) {
+ const SkScalar min = -max;
+ return r.fLeft > min && r.fTop > min &&
+ r.fRight < max && r.fBottom < max;
+}
+
+static bool safeRoundOut(const SkRect& src, SkIRect* dst, int32_t maxInt) {
+ const SkScalar maxScalar = SkIntToScalar(maxInt);
+ if (fitsInsideLimit(src, maxScalar)) {
+ src.roundOut(dst);
+ return true;
+ }
+ return false;
}
void SkScan::AntiFillPath(const SkPath& path, const SkRegion& origClip,
@@ -589,7 +595,14 @@ void SkScan::AntiFillPath(const SkPath& path, const SkRegion& origClip,
}
SkIRect ir;
- path.getBounds().roundOut(&ir);
+
+ if (!safeRoundOut(path.getBounds(), &ir, SK_MaxS32 >> SHIFT)) {
+#if 0
+ const SkRect& r = path.getBounds();
+ SkDebugf("--- bounds can't fit in SkIRect\n", r.fLeft, r.fTop, r.fRight, r.fBottom);
+#endif
+ return;
+ }
if (ir.isEmpty()) {
if (path.isInverseFillType()) {
blitter->blitRegion(origClip);
@@ -597,19 +610,6 @@ void SkScan::AntiFillPath(const SkPath& path, const SkRegion& origClip,
return;
}
-#if 0
- // use bit-or since we expect all to pass, so no need to go slower with
- // a short-circuiting logical-or
- if (overflows_short_shift(ir.fLeft, SHIFT) |
- overflows_short_shift(ir.fRight, SHIFT) |
- overflows_short_shift(ir.fTop, SHIFT) |
- overflows_short_shift(ir.fBottom, SHIFT)) {
- // can't supersample, so draw w/o antialiasing
- SkScan::FillPath(path, origClip, blitter);
- return;
- }
-#endif
-
// 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).
//