Add the ability to decode a subset to SkCodec

This allows codecs that support subsets natively (i.e. WEBP) to do so.

Add a field on SkCodec::Options representing the subset.

Add a method on SkCodec to find a valid subset which approximately
matches a desired subset.

Implement subset decodes in SkWebpCodec.

Add a test in DM for decoding subsets.
Notice that we only start on even boundaries. This is due to the
way libwebp's API works. SkWEBPImageDecoder does not take this into
account, which results in visual artifacts.

FIXME: Subsets with scaling are not pixel identical, but close. (This
may be fine, though - they are not perceptually different. We'll just
need to mark another set of images in gold as valid, once
https://skbug.com/4038 is fixed, so we can tests scaled webp without
generating new images on each run.)

Review URL: https://codereview.chromium.org/1240143002
diff --git a/tests/CodexTest.cpp b/tests/CodexTest.cpp
index f468205..82e490a 100644
--- a/tests/CodexTest.cpp
+++ b/tests/CodexTest.cpp
@@ -9,6 +9,7 @@
 #include "SkBitmap.h"
 #include "SkCodec.h"
 #include "SkMD5.h"
+#include "SkRandom.h"
 #include "SkScanlineDecoder.h"
 #include "Test.h"
 
@@ -41,10 +42,23 @@
     REPORTER_ASSERT(r, digest == goodDigest);
 }
 
+SkIRect generate_random_subset(SkRandom* rand, int w, int h) {
+    SkIRect rect;
+    do {
+        rect.fLeft = rand->nextRangeU(0, w);
+        rect.fTop = rand->nextRangeU(0, h);
+        rect.fRight = rand->nextRangeU(0, w);
+        rect.fBottom = rand->nextRangeU(0, h);
+        rect.sort();
+    } while (rect.isEmpty());
+    return rect;
+}
+
 static void check(skiatest::Reporter* r,
                   const char path[],
                   SkISize size,
-                  bool supportsScanlineDecoding) {
+                  bool supportsScanlineDecoding,
+                  bool supportsSubsetDecoding) {
     SkAutoTDelete<SkStream> stream(resource(path));
     if (!stream) {
         SkDebugf("Missing resource '%s'\n", path);
@@ -102,53 +116,88 @@
     } else {
         REPORTER_ASSERT(r, !scanlineDecoder);
     }
+
+    // The rest of this function tests decoding subsets, and will decode an arbitrary number of
+    // random subsets.
+    // Do not attempt to decode subsets of an image of only once pixel, since there is no
+    // meaningful subset.
+    if (size.width() * size.height() == 1) {
+        return;
+    }
+
+    SkRandom rand;
+    SkIRect subset;
+    SkCodec::Options opts;
+    opts.fSubset = &subset;
+    for (int i = 0; i < 5; i++) {
+        subset = generate_random_subset(&rand, size.width(), size.height());
+        SkASSERT(!subset.isEmpty());
+        const bool supported = codec->getValidSubset(&subset);
+        REPORTER_ASSERT(r, supported == supportsSubsetDecoding);
+
+        SkImageInfo subsetInfo = info.makeWH(subset.width(), subset.height());
+        SkBitmap bm;
+        bm.allocPixels(subsetInfo);
+        const SkCodec::Result result = codec->getPixels(bm.info(), bm.getPixels(), bm.rowBytes(),
+                                                        &opts, NULL, NULL);
+
+        if (supportsSubsetDecoding) {
+            REPORTER_ASSERT(r, result == SkCodec::kSuccess);
+            // Webp is the only codec that supports subsets, and it will have modified the subset
+            // to have even left/top.
+            REPORTER_ASSERT(r, SkIsAlign2(subset.fLeft) && SkIsAlign2(subset.fTop));
+        } else {
+            // No subsets will work.
+            REPORTER_ASSERT(r, result == SkCodec::kUnimplemented);
+        }
+    }
 }
 
 DEF_TEST(Codec, r) {
     // WBMP
-    check(r, "mandrill.wbmp", SkISize::Make(512, 512), false);
+    check(r, "mandrill.wbmp", SkISize::Make(512, 512), false, false);
 
     // WEBP
-    check(r, "baby_tux.webp", SkISize::Make(386, 395), false);
-    check(r, "color_wheel.webp", SkISize::Make(128, 128), false);
-    check(r, "yellow_rose.webp", SkISize::Make(400, 301), false);
+    check(r, "baby_tux.webp", SkISize::Make(386, 395), false, true);
+    check(r, "color_wheel.webp", SkISize::Make(128, 128), false, true);
+    check(r, "yellow_rose.webp", SkISize::Make(400, 301), false, true);
 
     // BMP
-    check(r, "randPixels.bmp", SkISize::Make(8, 8), false);
+    check(r, "randPixels.bmp", SkISize::Make(8, 8), false, false);
 
     // ICO
     // These two tests examine interestingly different behavior:
     // Decodes an embedded BMP image
-    check(r, "color_wheel.ico", SkISize::Make(128, 128), false);
+    check(r, "color_wheel.ico", SkISize::Make(128, 128), false, false);
     // Decodes an embedded PNG image
-    check(r, "google_chrome.ico", SkISize::Make(256, 256), false);
+    check(r, "google_chrome.ico", SkISize::Make(256, 256), false, false);
 
     // GIF
-    check(r, "box.gif", SkISize::Make(200, 55), false);
-    check(r, "color_wheel.gif", SkISize::Make(128, 128), false);
-    check(r, "randPixels.gif", SkISize::Make(8, 8), false);
+    check(r, "box.gif", SkISize::Make(200, 55), false, false);
+    check(r, "color_wheel.gif", SkISize::Make(128, 128), false, false);
+    check(r, "randPixels.gif", SkISize::Make(8, 8), false, false);
 
     // JPG
-    check(r, "CMYK.jpg", SkISize::Make(642, 516), true);
-    check(r, "color_wheel.jpg", SkISize::Make(128, 128), true);
-    check(r, "grayscale.jpg", SkISize::Make(128, 128), true);
-    check(r, "mandrill_512_q075.jpg", SkISize::Make(512, 512), true);
-    check(r, "randPixels.jpg", SkISize::Make(8, 8), true);
+    check(r, "CMYK.jpg", SkISize::Make(642, 516), true, false);
+    check(r, "color_wheel.jpg", SkISize::Make(128, 128), true, false);
+    check(r, "grayscale.jpg", SkISize::Make(128, 128), true, false);
+    check(r, "mandrill_512_q075.jpg", SkISize::Make(512, 512), true, false);
+    check(r, "randPixels.jpg", SkISize::Make(8, 8), true, false);
 
     // PNG
-    check(r, "arrow.png", SkISize::Make(187, 312), true);
-    check(r, "baby_tux.png", SkISize::Make(240, 246), true);
-    check(r, "color_wheel.png", SkISize::Make(128, 128), true);
-    check(r, "half-transparent-white-pixel.png", SkISize::Make(1, 1), true);
-    check(r, "mandrill_128.png", SkISize::Make(128, 128), true);
-    check(r, "mandrill_16.png", SkISize::Make(16, 16), true);
-    check(r, "mandrill_256.png", SkISize::Make(256, 256), true);
-    check(r, "mandrill_32.png", SkISize::Make(32, 32), true);
-    check(r, "mandrill_512.png", SkISize::Make(512, 512), true);
-    check(r, "mandrill_64.png", SkISize::Make(64, 64), true);
-    check(r, "plane.png", SkISize::Make(250, 126), true);
-    check(r, "randPixels.png", SkISize::Make(8, 8), true);
-    check(r, "yellow_rose.png", SkISize::Make(400, 301), true);
+    check(r, "arrow.png", SkISize::Make(187, 312), true, false);
+    check(r, "baby_tux.png", SkISize::Make(240, 246), true, false);
+    check(r, "color_wheel.png", SkISize::Make(128, 128), true, false);
+    check(r, "half-transparent-white-pixel.png", SkISize::Make(1, 1), true, false);
+    check(r, "mandrill_128.png", SkISize::Make(128, 128), true, false);
+    check(r, "mandrill_16.png", SkISize::Make(16, 16), true, false);
+    check(r, "mandrill_256.png", SkISize::Make(256, 256), true, false);
+    check(r, "mandrill_32.png", SkISize::Make(32, 32), true, false);
+    check(r, "mandrill_512.png", SkISize::Make(512, 512), true, false);
+    check(r, "mandrill_64.png", SkISize::Make(64, 64), true, false);
+    check(r, "plane.png", SkISize::Make(250, 126), true, false);
+    check(r, "randPixels.png", SkISize::Make(8, 8), true, false);
+    check(r, "yellow_rose.png", SkISize::Make(400, 301), true, false);
 }
 
 static void test_invalid_stream(skiatest::Reporter* r, const void* stream, size_t len) {