aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/core/SkScan_AntiPath.cpp43
-rw-r--r--tests/ClipCubicTest.cpp20
2 files changed, 51 insertions, 12 deletions
diff --git a/src/core/SkScan_AntiPath.cpp b/src/core/SkScan_AntiPath.cpp
index 97843ef7c3..77171b3984 100644
--- a/src/core/SkScan_AntiPath.cpp
+++ b/src/core/SkScan_AntiPath.cpp
@@ -561,9 +561,9 @@ static int overflows_short_shift(int value, int shift) {
return (value << s >> s) - value;
}
-void SkScan::AntiFillPath(const SkPath& path, const SkRegion& clip,
+void SkScan::AntiFillPath(const SkPath& path, const SkRegion& origClip,
SkBlitter* blitter, bool forceRLE) {
- if (clip.isEmpty()) {
+ if (origClip.isEmpty()) {
return;
}
@@ -571,7 +571,7 @@ void SkScan::AntiFillPath(const SkPath& path, const SkRegion& clip,
path.getBounds().roundOut(&ir);
if (ir.isEmpty()) {
if (path.isInverseFillType()) {
- blitter->blitRegion(clip);
+ blitter->blitRegion(origClip);
}
return;
}
@@ -583,16 +583,35 @@ void SkScan::AntiFillPath(const SkPath& path, const SkRegion& clip,
overflows_short_shift(ir.fTop, SHIFT) |
overflows_short_shift(ir.fBottom, SHIFT)) {
// can't supersample, so draw w/o antialiasing
- SkScan::FillPath(path, clip, blitter);
+ SkScan::FillPath(path, origClip, blitter);
return;
}
- SkScanClipper clipper(blitter, &clip, ir);
+ // 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...
+ SkRegion tmpClipStorage;
+ const SkRegion* clipRgn = &origClip;
+ {
+ static const int32_t kMaxClipCoord = 32767;
+ const SkIRect& bounds = origClip.getBounds();
+ if (bounds.fRight > kMaxClipCoord || bounds.fBottom > kMaxClipCoord) {
+ SkIRect limit = { 0, 0, kMaxClipCoord, kMaxClipCoord };
+ tmpClipStorage.op(origClip, limit, SkRegion::kIntersect_Op);
+ clipRgn = &tmpClipStorage;
+ }
+ }
+ // for here down, use clipRgn, not origClip
+
+ SkScanClipper clipper(blitter, clipRgn, ir);
const SkIRect* clipRect = clipper.getClipRect();
if (clipper.getBlitter() == NULL) { // clipped out
if (path.isInverseFillType()) {
- blitter->blitRegion(clip);
+ blitter->blitRegion(*clipRgn);
}
return;
}
@@ -601,7 +620,7 @@ void SkScan::AntiFillPath(const SkPath& path, const SkRegion& clip,
blitter = clipper.getBlitter();
if (path.isInverseFillType()) {
- sk_blit_above(blitter, ir, clip);
+ sk_blit_above(blitter, ir, *clipRgn);
}
SkIRect superRect, *superClipRect = NULL;
@@ -617,16 +636,16 @@ void SkScan::AntiFillPath(const SkPath& path, const SkRegion& clip,
// MaskSuperBlitter can't handle drawing outside of ir, so we can't use it
// if we're an inverse filltype
if (!path.isInverseFillType() && MaskSuperBlitter::CanHandleRect(ir) && !forceRLE) {
- MaskSuperBlitter superBlit(blitter, ir, clip);
+ MaskSuperBlitter superBlit(blitter, ir, *clipRgn);
SkASSERT(SkIntToScalar(ir.fTop) <= path.getBounds().fTop);
- sk_fill_path(path, superClipRect, &superBlit, ir.fTop, ir.fBottom, SHIFT, clip);
+ sk_fill_path(path, superClipRect, &superBlit, ir.fTop, ir.fBottom, SHIFT, *clipRgn);
} else {
- SuperBlitter superBlit(blitter, ir, clip);
- sk_fill_path(path, superClipRect, &superBlit, ir.fTop, ir.fBottom, SHIFT, clip);
+ SuperBlitter superBlit(blitter, ir, *clipRgn);
+ sk_fill_path(path, superClipRect, &superBlit, ir.fTop, ir.fBottom, SHIFT, *clipRgn);
}
if (path.isInverseFillType()) {
- sk_blit_below(blitter, ir, clip);
+ sk_blit_below(blitter, ir, *clipRgn);
}
}
diff --git a/tests/ClipCubicTest.cpp b/tests/ClipCubicTest.cpp
index 931b61e09c..491d0e5f3e 100644
--- a/tests/ClipCubicTest.cpp
+++ b/tests/ClipCubicTest.cpp
@@ -7,9 +7,27 @@
*/
#include "Test.h"
+#include "SkCanvas.h"
+#include "SkPaint.h"
#include "SkCubicClipper.h"
#include "SkGeometry.h"
+// Currently the supersampler blitter uses int16_t for its index into an array
+// the width of the clip. Test that we don't crash/assert if we try to draw
+// with a device/clip that is larger.
+static void test_giantClip() {
+ SkBitmap bm;
+ bm.setConfig(SkBitmap::kARGB_8888_Config, 64919, 1);
+ bm.allocPixels();
+ SkCanvas canvas(bm);
+ canvas.clear(0);
+
+ SkPath path;
+ path.moveTo(0, 0); path.lineTo(1, 0); path.lineTo(33, 1);
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ canvas.drawPath(path, paint);
+}
static void PrintCurve(const char *name, const SkPoint crv[4]) {
printf("%s: %.10g, %.10g, %.10g, %.10g, %.10g, %.10g, %.10g, %.10g\n",
@@ -142,6 +160,8 @@ static void TestCubicClipping(skiatest::Reporter* reporter) {
1.297736168, 7.059780121,
2.505550385, 10,
shouldbe), tol));
+
+ test_giantClip();
}