test (and fix) clip_restriction in canvas

BUG=skia:

Change-Id: I86d25d0fd82be35d01471fba59f77b360be5373c
Reviewed-on: https://skia-review.googlesource.com/9995
Reviewed-by: Derek Sollenberger <djsollen@google.com>
Commit-Queue: Derek Sollenberger <djsollen@google.com>
diff --git a/tests/CanvasTest.cpp b/tests/CanvasTest.cpp
index cfdce62..d18324a 100644
--- a/tests/CanvasTest.cpp
+++ b/tests/CanvasTest.cpp
@@ -44,6 +44,7 @@
  *      works the same way as SIMPLE_TEST_STEP, and additionally verifies
  *      that the invoked method returns a non-zero value.
  */
+
 #include "SkBitmap.h"
 #include "SkCanvas.h"
 #include "SkClipStack.h"
@@ -103,6 +104,59 @@
     }
 }
 
+const SkIRect gBaseRestrictedR = { 0, 0, 10, 10 };
+
+static void test_restriction(skiatest::Reporter* reporter, SkCanvas* canvas) {
+    REPORTER_ASSERT(reporter, canvas->getDeviceClipBounds() == gBaseRestrictedR);
+
+    const SkIRect restrictionR = { 2, 2, 8, 8 };
+    canvas->androidFramework_setDeviceClipRestriction(restrictionR);
+    REPORTER_ASSERT(reporter, canvas->getDeviceClipBounds() == restrictionR);
+
+    const SkIRect clipR = { 4, 4, 6, 6 };
+    canvas->clipRect(SkRect::Make(clipR), SkClipOp::kIntersect);
+    REPORTER_ASSERT(reporter, canvas->getDeviceClipBounds() == clipR);
+
+    // now test that expanding clipops can't exceed the restriction
+    const SkClipOp expanders[] = {
+        SkClipOp::kUnion_deprecated,
+        SkClipOp::kXOR_deprecated,
+        SkClipOp::kReverseDifference_deprecated,
+        SkClipOp::kReplace_deprecated,
+    };
+
+    const SkRect expandR = { 0, 0, 5, 9 };
+    SkASSERT(!SkRect::Make(restrictionR).contains(expandR));
+
+    for (SkClipOp op : expanders) {
+        canvas->save();
+        canvas->clipRect(expandR, op);
+        REPORTER_ASSERT(reporter, gBaseRestrictedR.contains(canvas->getDeviceClipBounds()));
+        canvas->restore();
+    }
+}
+
+/**
+ *  Clip restriction logic exists in the canvas itself, and in various kinds of devices.
+ *
+ *  This test explicitly tries to exercise that variety:
+ *  - picture : empty device but exercises canvas itself
+ *  - pdf : uses SkClipStack in its device (as does SVG and GPU)
+ *  - raster : uses SkRasterClip in its device
+ */
+DEF_TEST(canvas_clip_restriction, reporter) {
+    test_restriction(reporter, SkPictureRecorder().beginRecording(SkRect::Make(gBaseRestrictedR)));
+
+    SkNullWStream stream;
+    auto doc = SkDocument::MakePDF(&stream);
+    test_restriction(reporter, doc->beginPage(SkIntToScalar(gBaseRestrictedR.width()),
+                                              SkIntToScalar(gBaseRestrictedR.height())));
+
+    auto surf = SkSurface::MakeRasterN32Premul(gBaseRestrictedR.width(),
+                                               gBaseRestrictedR.height(), nullptr);
+    test_restriction(reporter, surf->getCanvas());
+}
+
 static const int kWidth = 2, kHeight = 2;
 
 static void createBitmap(SkBitmap* bm, SkColor color) {