remove unused (by the outside) SkImage::newSurface, and simplify newImage -> newSubset

BUG=skia:

Review URL: https://codereview.chromium.org/1364443002
diff --git a/gm/drawbitmaprect.cpp b/gm/drawbitmaprect.cpp
index dd6d2b7..2f33627 100644
--- a/gm/drawbitmaprect.cpp
+++ b/gm/drawbitmaprect.cpp
@@ -89,33 +89,6 @@
     canvas->drawImageRect(image, srcR, dstR, nullptr);
 }
 
-static void imagescaleproc(SkCanvas* canvas, SkImage* image, const SkBitmap&, const SkIRect& srcIR,
-                           const SkRect& dstR) {
-    const int newW = SkScalarRoundToInt(dstR.width());
-    const int newH = SkScalarRoundToInt(dstR.height());
-    SkAutoTUnref<SkImage> newImage(image->newImage(newW, newH, &srcIR));
-
-#ifdef SK_DEBUG
-    const SkIRect baseR = SkIRect::MakeWH(image->width(), image->height());
-    const bool containsSubset = baseR.contains(srcIR);
-#endif
-
-    if (newImage) {
-        SkASSERT(containsSubset);
-        canvas->drawImage(newImage, dstR.x(), dstR.y());
-    } else {
-        // newImage() does not support subsets that are not contained by the original
-        // but drawImageRect does, so we just draw an X in its place to indicate that we are
-        // deliberately not drawing here.
-        SkASSERT(!containsSubset);
-        SkPaint paint;
-        paint.setStyle(SkPaint::kStroke_Style);
-        paint.setStrokeWidth(4);
-        canvas->drawLine(4, 4, newW - 4.0f, newH - 4.0f, paint);
-        canvas->drawLine(4, newH - 4.0f, newW - 4.0f, 4, paint);
-    }
-}
-
 typedef void DrawRectRectProc(SkCanvas*, SkImage*, const SkBitmap&, const SkIRect&, const SkRect&);
 
 static const int gSize = 1024;
@@ -228,4 +201,3 @@
 
 DEF_GM( return new DrawBitmapRectGM(canvasproc, nullptr); )
 DEF_GM( return new DrawBitmapRectGM(imageproc, "-imagerect"); )
-DEF_GM( return new DrawBitmapRectGM(imagescaleproc, "-imagescale"); )
diff --git a/gm/image.cpp b/gm/image.cpp
index 726ab97..27cce23 100644
--- a/gm/image.cpp
+++ b/gm/image.cpp
@@ -192,96 +192,3 @@
     typedef skiagm::GM INHERITED;
 };
 DEF_GM( return new ImageGM; )
-
-class ImageResizeGM : public skiagm::GM {
-    enum {
-        W = 100,
-        H = 100,
-    };
-public:
-    ImageResizeGM() {}
-
-protected:
-    SkString onShortName() override { return SkString("image-resize"); }
-
-    SkISize onISize() override { return SkISize::Make(510, 480); }
-
-    void drawIntoImage(SkCanvas* canvas) {
-        SkPaint paint;
-        paint.setAntiAlias(true);
-        paint.setStyle(SkPaint::kStroke_Style);
-        paint.setStrokeWidth(3);
-        SkRandom rand;
-        for (int i = 0; i < 60; ++i) {
-            paint.setColor(rand.nextU());
-            SkScalar x = rand.nextUScalar1() * W;
-            SkScalar y = rand.nextUScalar1() * H;
-            SkScalar r = rand.nextUScalar1() * W / 2;
-            canvas->drawCircle(x, y, r, paint);
-        }
-    }
-
-    SkImage* makeImage(SkCanvas* canvas) {
-        const SkImageInfo info = SkImageInfo::MakeN32Premul(W, H);
-        SkAutoTUnref<SkSurface> surface(canvas->newSurface(info));
-        if (!surface) {
-            surface.reset(SkSurface::NewRaster(info));
-        }
-        this->drawIntoImage(surface->getCanvas());
-        return surface->newImageSnapshot();
-    }
-
-    void drawResized(SkCanvas* canvas, SkImage* image, int newW, int newH, const SkIRect* subset,
-                     SkFilterQuality fq) {
-        // canvas method
-        SkPaint paint;
-        paint.setFilterQuality(fq);
-        SkRect dstR = SkRect::MakeWH(SkIntToScalar(newW), SkIntToScalar(newH));
-        SkRect srcR;
-        if (subset) {
-            srcR.set(*subset);
-        }
-        canvas->legacy_drawImageRect(image, subset ? &srcR : nullptr, dstR, &paint);
-        canvas->translate(newW + 20.0f, 0);
-
-        // image method
-        SkAutoTUnref<SkImage> image2(image->newImage(newW, newH, subset, fq));
-        canvas->drawImage(image2, 0, 0, nullptr);
-        canvas->translate(image2->width() + 20.0f, 0);
-    }
-
-    void drawImage(SkCanvas* canvas, SkImage* image, SkFilterQuality fq) {
-
-        canvas->drawImage(image, 0, 0, nullptr);
-        canvas->translate(image->width() + 20.0f, 0);
-        this->drawResized(canvas, image, image->width()*4/10, image->height()*4/10, nullptr, fq);
-
-        SkIRect subset = SkIRect::MakeLTRB(W/4, H/4, W/2, H/2);
-        this->drawResized(canvas, image, W, H, &subset, fq);
-    }
-
-    void onDraw(SkCanvas* canvas) override {
-        canvas->translate(10, 10);
-
-        SkAutoTUnref<SkImage> image(this->makeImage(canvas));
-
-        const SkFilterQuality fq[] = {
-            kNone_SkFilterQuality,
-            kLow_SkFilterQuality,
-            kMedium_SkFilterQuality,
-            kHigh_SkFilterQuality,
-        };
-        for (size_t i = 0; i < SK_ARRAY_COUNT(fq); ++i) {
-            {
-                SkAutoCanvasRestore acr(canvas, true);
-                this->drawImage(canvas, image, fq[i]);
-            }
-            canvas->translate(0, image->height() + 20.0f);
-        }
-    }
-    
-private:
-    typedef skiagm::GM INHERITED;
-};
-DEF_GM( return new ImageResizeGM; )
-
diff --git a/gm/image_pict.cpp b/gm/image_pict.cpp
index 19271c1..53ae990 100644
--- a/gm/image_pict.cpp
+++ b/gm/image_pict.cpp
@@ -326,7 +326,7 @@
         // No API to draw a GrTexture directly, so we cheat and create a private image subclass
         SkAutoTUnref<SkImage> image(new SkImage_Gpu(cache->info().width(), cache->info().height(),
                                                     cache->uniqueID(), kPremul_SkAlphaType, texture,
-                                                    0, SkSurface::kNo_Budgeted));
+                                                    SkSurface::kNo_Budgeted));
         canvas->drawImage(image, x, y);
 #endif
     }
diff --git a/gm/surface.cpp b/gm/surface.cpp
index bf7f931..8c7c118 100644
--- a/gm/surface.cpp
+++ b/gm/surface.cpp
@@ -143,7 +143,7 @@
         SkAutoTUnref<SkImage> image(surf->newImageSnapshot());
         canvas->drawImage(image, 10, 10, nullptr);
 
-        SkAutoTUnref<SkSurface> surf2(image->newSurface(info, nullptr));
+        SkAutoTUnref<SkSurface> surf2(surf->newSurface(info));
         drawInto(surf2->getCanvas());
 
         // Assert that the props were communicated transitively through the first image
diff --git a/include/core/SkImage.h b/include/core/SkImage.h
index 90448d8..99562f4 100644
--- a/include/core/SkImage.h
+++ b/include/core/SkImage.h
@@ -270,17 +270,9 @@
      */
     SkData* refEncoded() const;
 
-    /**
-     *  Return a new surface that is compatible with this image's internal representation
-     *  (e.g. raster or gpu).
-     *
-     *  If no surfaceprops are specified, the image will attempt to match the props of when it
-     *  was created (if it came from a surface).
-     */
-    SkSurface* newSurface(const SkImageInfo&, const SkSurfaceProps* = NULL) const;
-
     const char* toString(SkString*) const;
 
+#ifdef SK_SUPPORT_LEGACY_NEWIMAGE
     /**
      *  Return an image that is a rescale of this image (using newWidth, newHeight).
      *
@@ -299,8 +291,17 @@
      *    since during drawing we will "apply the alpha" to the pixels. Future optimizations
      *    may take away this caveat, preserving unpremul.
      */
-    SkImage* newImage(int newWidth, int newHeight, const SkIRect* subset = NULL,
-                      SkFilterQuality = kNone_SkFilterQuality) const;
+    SkImage* newImage(int newWidth, int newHeight, const SkIRect* subset) const;
+#endif
+
+    /**
+     *  Return a new image that is a subset of this image. The underlying implementation may
+     *  share the pixels, or it may make a copy.
+     *
+     *  If subset does not intersect the bounds of this image, or the copy/share cannot be made,
+     *  NULL will be returned.
+     */
+    SkImage* newSubset(const SkIRect& subset) const;
 
     // Helper functions to convert to SkBitmap
 
diff --git a/samplecode/SampleFilterQuality.cpp b/samplecode/SampleFilterQuality.cpp
index 8bc2b07..f5558d8 100644
--- a/samplecode/SampleFilterQuality.cpp
+++ b/samplecode/SampleFilterQuality.cpp
@@ -46,14 +46,14 @@
     return surface->newImageSnapshot();
 }
 
-static SkImage* zoom_up(SkImage* orig) {
+static SkImage* zoom_up(SkSurface* origSurf, SkImage* orig) {
     const SkScalar S = 8;    // amount to scale up
     const int D = 2;    // dimension scaling for the offscreen
     // since we only view the center, don't need to produce the entire thing
     
     SkImageInfo info = SkImageInfo::MakeN32(orig->width() * D, orig->height() * D,
                                             kOpaque_SkAlphaType);
-    SkAutoTUnref<SkSurface> surface(orig->newSurface(info));
+    SkAutoTUnref<SkSurface> surface(origSurf->newSurface(info));
     SkCanvas* canvas = surface->getCanvas();
     canvas->drawColor(SK_ColorWHITE);
     canvas->scale(S, S);
@@ -221,7 +221,7 @@
 
         if (surface) {
             SkAutoTUnref<SkImage> orig(surface->newImageSnapshot());
-            SkAutoTUnref<SkImage> zoomed(zoom_up(orig));
+            SkAutoTUnref<SkImage> zoomed(zoom_up(surface, orig));
             origCanvas->drawImage(zoomed,
                                   SkScalarHalf(fCell.width() - zoomed->width()),
                                   SkScalarHalf(fCell.height() - zoomed->height()));
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
index 6f46557..032be19 100644
--- a/src/image/SkImage.cpp
+++ b/src/image/SkImage.cpp
@@ -126,21 +126,15 @@
     return generator ? SkImage::NewFromGenerator(generator, subset) : nullptr;
 }
 
-SkSurface* SkImage::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) const {
-    if (nullptr == props) {
-        props = &as_IB(this)->props();
-    }
-    return as_IB(this)->onNewSurface(info, *props);
-}
-
 const char* SkImage::toString(SkString* str) const {
     str->appendf("image: (id:%d (%d, %d) %s)", this->uniqueID(), this->width(), this->height(),
                  this->isOpaque() ? "opaque" : "");
     return str->c_str();
 }
 
-SkImage* SkImage::newImage(int newWidth, int newHeight, const SkIRect* subset,
-                           SkFilterQuality quality) const {
+#ifdef SK_SUPPORT_LEGACY_NEWIMAGE
+SkImage* SkImage::newImage(int newWidth, int newHeight, const SkIRect* subset) const {
+#if 0
     if (newWidth <= 0 || newHeight <= 0) {
         return nullptr;
     }
@@ -161,6 +155,30 @@
     }
 
     return as_IB(this)->onNewImage(newWidth, newHeight, subset, quality);
+#else
+    SkASSERT(subset);
+    SkASSERT(subset->width() == newWidth);
+    SkASSERT(subset->height() == newHeight);
+    return this->newSubset(*subset);
+#endif
+}
+#endif
+
+SkImage* SkImage::newSubset(const SkIRect& subset) const {
+    if (subset.isEmpty()) {
+        return nullptr;
+    }
+
+    const SkIRect bounds = SkIRect::MakeWH(this->width(), this->height());
+    if (!bounds.contains(subset)) {
+        return nullptr;
+    }
+
+    // optimization : return self if the subset == our bounds
+    if (bounds == subset) {
+        return SkRef(const_cast<SkImage*>(this));
+    }
+    return as_IB(this)->onNewSubset(subset);
 }
 
 #if SK_SUPPORT_GPU
@@ -244,33 +262,6 @@
     return true;
 }
 
-SkImage* SkImage_Base::onNewImage(int newWidth, int newHeight, const SkIRect* subset,
-                                  SkFilterQuality quality) const {
-    const bool opaque = this->isOpaque();
-    const SkImageInfo info = SkImageInfo::Make(newWidth, newHeight, kN32_SkColorType,
-                                               opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
-    SkAutoTUnref<SkSurface> surface(this->newSurface(info, nullptr));
-    if (!surface.get()) {
-        return nullptr;
-    }
-
-    SkRect src;
-    if (subset) {
-        src.set(*subset);
-    } else {
-        src = SkRect::MakeIWH(this->width(), this->height());
-    }
-
-    surface->getCanvas()->scale(newWidth / src.width(), newHeight / src.height());
-    surface->getCanvas()->translate(-src.x(), -src.y());
-
-    SkPaint paint;
-    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
-    paint.setFilterQuality(quality);
-    surface->getCanvas()->drawImage(this, 0, 0, &paint);
-    return surface->newImageSnapshot();
-}
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 bool SkImage::peekPixels(SkPixmap* pmap) const {
@@ -311,7 +302,7 @@
         }
         const SkImageInfo info = bm.info();
         return new SkImage_Gpu(info.width(), info.height(), bm.getGenerationID(), info.alphaType(),
-                               tex, 0, SkSurface::kNo_Budgeted);
+                               tex, SkSurface::kNo_Budgeted);
     }
 #endif
 
diff --git a/src/image/SkImage_Base.h b/src/image/SkImage_Base.h
index d0cb8d5..bbcf182 100644
--- a/src/image/SkImage_Base.h
+++ b/src/image/SkImage_Base.h
@@ -37,8 +37,6 @@
 
     const SkSurfaceProps& props() const { return fProps; }
 
-    virtual SkSurface* onNewSurface(const SkImageInfo&, const SkSurfaceProps&) const = 0;
-
     virtual const void* onPeekPixels(SkImageInfo*, size_t* /*rowBytes*/) const {
         return nullptr;
     }
@@ -60,9 +58,7 @@
                                   SkShader::TileMode,
                                   const SkMatrix* localMatrix) const { return nullptr; }
 
-    // newWidth > 0, newHeight > 0, subset either nullptr or a proper subset of this bounds
-    virtual SkImage* onNewImage(int newWidth, int newHeight, const SkIRect* subset,
-                                SkFilterQuality) const;
+    virtual SkImage* onNewSubset(const SkIRect&) const = 0;
     virtual SkData* onRefEncoded() const { return nullptr; }
 
     virtual bool onAsLegacyBitmap(SkBitmap*, LegacyBitmapMode) const;
diff --git a/src/image/SkImage_Generator.cpp b/src/image/SkImage_Generator.cpp
index 4981f37..765234f 100644
--- a/src/image/SkImage_Generator.cpp
+++ b/src/image/SkImage_Generator.cpp
@@ -7,6 +7,7 @@
 
 #include "SkImage_Base.h"
 #include "SkBitmap.h"
+#include "SkCanvas.h"
 #include "SkData.h"
 #include "SkImageCacherator.h"
 #include "SkImagePriv.h"
@@ -20,12 +21,11 @@
         , fCache(cache) // take ownership
     {}
 
-    SkSurface* onNewSurface(const SkImageInfo&, const SkSurfaceProps&) const override;
     bool onReadPixels(const SkImageInfo&, void*, size_t, int srcX, int srcY) const override;
     const void* onPeekPixels(SkImageInfo*, size_t* /*rowBytes*/) const override;
     SkData* onRefEncoded() const override;
     bool isOpaque() const override { return fCache->info().isOpaque(); }
-
+    SkImage* onNewSubset(const SkIRect&) const override;
     bool getROPixels(SkBitmap*) const override;
     GrTexture* asTextureRef(GrContext*, SkImageUsageType) const override;
 
@@ -54,11 +54,6 @@
     return nullptr;
 }
 
-SkSurface* SkImage_Generator::onNewSurface(const SkImageInfo& info,
-                                           const SkSurfaceProps& props) const {
-    return SkSurface::NewRaster(info, &props);
-}
-
 bool SkImage_Generator::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
                                      int srcX, int srcY) const {
     SkBitmap bm;
@@ -84,6 +79,22 @@
     return fCache->lockAsTexture(ctx, usage, this);
 }
 
+SkImage* SkImage_Generator::onNewSubset(const SkIRect& subset) const {
+    // TODO: make this lazy, by wrapping the subset inside a new generator or something
+    // For now, we do effectively what we did before, make it a raster
+
+    const SkImageInfo info = SkImageInfo::MakeN32(subset.width(), subset.height(),
+                                      this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
+    SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(info));
+    if (!surface) {
+        return nullptr;
+    }
+    surface->getCanvas()->clear(0);
+    surface->getCanvas()->drawImage(this, SkIntToScalar(-subset.x()), SkIntToScalar(-subset.y()),
+                                    nullptr);
+    return surface->newImageSnapshot();
+}
+
 SkImage* SkImage::NewFromGenerator(SkImageGenerator* generator, const SkIRect* subset) {
     SkImageCacherator* cache = SkImageCacherator::NewFromGenerator(generator, subset);
     if (!cache) {
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index 163e62e..1a63a0d 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -15,10 +15,9 @@
 #include "SkPixelRef.h"
 
 SkImage_Gpu::SkImage_Gpu(int w, int h, uint32_t uniqueID, SkAlphaType at, GrTexture* tex,
-                         int sampleCountForNewSurfaces, SkSurface::Budgeted budgeted)
+                         SkSurface::Budgeted budgeted)
     : INHERITED(w, h, uniqueID, nullptr)
     , fTexture(SkRef(tex))
-    , fSampleCountForNewSurfaces(sampleCountForNewSurfaces)
     , fAlphaType(at)
     , fBudgeted(budgeted)
     , fAddedRasterVersionToCache(false)
@@ -30,19 +29,6 @@
     }
 }
 
-SkSurface* SkImage_Gpu::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) const {
-    GrTexture* tex = this->getTexture();
-    SkASSERT(tex);
-    GrContext* ctx = tex->getContext();
-    if (!ctx) {
-        // the texture may have been abandoned, so we have to check
-        return nullptr;
-    }
-    // TODO: Change signature of onNewSurface to take a budgeted param.
-    const SkSurface::Budgeted budgeted = SkSurface::kNo_Budgeted;
-    return SkSurface::NewRenderTarget(ctx, budgeted, info, fSampleCountForNewSurfaces, &props);
-}
-
 extern void SkTextureImageApplyBudgetedDecision(SkImage* image) {
     if (as_IB(image)->getTexture()) {
         ((SkImage_Gpu*)image)->applyBudgetDecision();
@@ -136,6 +122,22 @@
     return true;
 }
 
+SkImage* SkImage_Gpu::onNewSubset(const SkIRect& subset) const {
+    GrContext* ctx = fTexture->getContext();
+    GrSurfaceDesc desc = fTexture->desc();
+    desc.fWidth = subset.width();
+    desc.fHeight = subset.height();
+
+    GrTexture* subTx = ctx->textureProvider()->createTexture(desc,
+                                                             SkSurface::kYes_Budgeted == fBudgeted);
+    if (!subTx) {
+        return nullptr;
+    }
+    ctx->copySurface(subTx, fTexture, subset, SkIPoint::Make(0, 0));
+    return new SkImage_Gpu(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID, fAlphaType, subTx,
+                           fBudgeted);
+}
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 static SkImage* new_wrapped_texture_common(GrContext* ctx, const GrBackendTextureDesc& desc,
@@ -154,7 +156,7 @@
     }
 
     const SkSurface::Budgeted budgeted = SkSurface::kNo_Budgeted;
-    return new SkImage_Gpu(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID, at, tex, 0, budgeted);
+    return new SkImage_Gpu(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID, at, tex, budgeted);
 }
 
 SkImage* SkImage::NewFromTexture(GrContext* ctx, const GrBackendTextureDesc& desc, SkAlphaType at,
@@ -186,8 +188,7 @@
     }
 
     const SkSurface::Budgeted budgeted = SkSurface::kYes_Budgeted;
-    const int sampleCount = 0;  // todo: make this an explicit parameter to newSurface()?
-    return new SkImage_Gpu(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID, at, dst, sampleCount,
+    return new SkImage_Gpu(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID, at, dst,
                            budgeted);
 }
 
@@ -267,7 +268,7 @@
     drawContext->drawRect(dst->asRenderTarget(), GrClip::WideOpen(), paint, SkMatrix::I(), rect);
     ctx->flushSurfaceWrites(dst);
     return new SkImage_Gpu(dstDesc.fWidth, dstDesc.fHeight, kNeedNewImageUniqueID,
-                           kOpaque_SkAlphaType, dst, 0, budgeted);
+                           kOpaque_SkAlphaType, dst, budgeted);
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/image/SkImage_Gpu.h b/src/image/SkImage_Gpu.h
index d168fb6..5e847dd 100644
--- a/src/image/SkImage_Gpu.h
+++ b/src/image/SkImage_Gpu.h
@@ -22,8 +22,7 @@
      *  An "image" can be a subset/window into a larger texture, so we explicit take the
      *  width and height.
      */
-    SkImage_Gpu(int w, int h, uint32_t uniqueID, SkAlphaType, GrTexture*,
-                int sampleCountForNewSurfaces, SkSurface::Budgeted);
+    SkImage_Gpu(int w, int h, uint32_t uniqueID, SkAlphaType, GrTexture*, SkSurface::Budgeted);
     ~SkImage_Gpu() override;
 
     void applyBudgetDecision() const {
@@ -38,19 +37,18 @@
 
     bool getROPixels(SkBitmap*) const override;
     GrTexture* asTextureRef(GrContext* ctx, SkImageUsageType usage) const override;
+    SkImage* onNewSubset(const SkIRect&) const override;
 
     GrTexture* peekTexture() const override { return fTexture; }
     SkShader* onNewShader(SkShader::TileMode,
                           SkShader::TileMode,
                           const SkMatrix* localMatrix) const override;
     bool isOpaque() const override;
-    SkSurface* onNewSurface(const SkImageInfo&, const SkSurfaceProps&) const override;
     bool onReadPixels(const SkImageInfo&, void* dstPixels, size_t dstRowBytes,
                       int srcX, int srcY) const override;
 
 private:
     SkAutoTUnref<GrTexture>     fTexture;
-    const int                   fSampleCountForNewSurfaces;   // 0 if we don't know
     const SkAlphaType           fAlphaType;
     const SkSurface::Budgeted   fBudgeted;
     mutable SkAtomic<bool>      fAddedRasterVersionToCache;
diff --git a/src/image/SkImage_Raster.cpp b/src/image/SkImage_Raster.cpp
index 67498f0..30ea7cc 100644
--- a/src/image/SkImage_Raster.cpp
+++ b/src/image/SkImage_Raster.cpp
@@ -67,12 +67,12 @@
     SkImage_Raster(const SkImageInfo&, SkData*, size_t rb, SkColorTable*, const SkSurfaceProps*);
     virtual ~SkImage_Raster();
 
-    SkSurface* onNewSurface(const SkImageInfo&, const SkSurfaceProps&) const override;
     bool onReadPixels(const SkImageInfo&, void*, size_t, int srcX, int srcY) const override;
     const void* onPeekPixels(SkImageInfo*, size_t* /*rowBytes*/) const override;
     SkData* onRefEncoded() const override;
     bool getROPixels(SkBitmap*) const override;
     GrTexture* asTextureRef(GrContext*, SkImageUsageType) const override;
+    SkImage* onNewSubset(const SkIRect&) const override;
 
     // exposed for SkSurface_Raster via SkNewImageFromPixelRef
     SkImage_Raster(const SkImageInfo&, SkPixelRef*, const SkIPoint& pixelRefOrigin, size_t rowBytes,
@@ -149,10 +149,6 @@
     return SkShader::CreateBitmapShader(fBitmap, tileX, tileY, localMatrix);
 }
 
-SkSurface* SkImage_Raster::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) const {
-    return SkSurface::NewRaster(info, &props);
-}
-
 bool SkImage_Raster::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
                                   int srcX, int srcY) const {
     SkBitmap shallowCopy(fBitmap);
@@ -212,6 +208,20 @@
     return nullptr;
 }
 
+SkImage* SkImage_Raster::onNewSubset(const SkIRect& subset) const {
+    // TODO : could consider heurist of sharing pixels, if subset is pretty close to complete
+
+    SkImageInfo info = SkImageInfo::MakeN32(subset.width(), subset.height(), fBitmap.alphaType());
+    SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(info));
+    if (!surface) {
+        return nullptr;
+    }
+    surface->getCanvas()->clear(0);
+    surface->getCanvas()->drawImage(this, SkIntToScalar(-subset.x()), SkIntToScalar(-subset.y()),
+                                    nullptr);
+    return surface->newImageSnapshot();
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 SkImage* SkImage::NewRasterCopy(const SkImageInfo& info, const void* pixels, size_t rowBytes,
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index c0c6b6e..b705f47 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -16,7 +16,6 @@
 
 #if SK_SUPPORT_GPU
 
-///////////////////////////////////////////////////////////////////////////////
 SkSurface_Gpu::SkSurface_Gpu(SkGpuDevice* device)
     : INHERITED(device->width(), device->height(), &device->surfaceProps())
     , fDevice(SkRef(device)) {
@@ -80,12 +79,11 @@
 
 SkImage* SkSurface_Gpu::onNewImageSnapshot(Budgeted budgeted) {
     const SkImageInfo info = fDevice->imageInfo();
-    const int sampleCount = fDevice->accessRenderTarget()->numColorSamples();
     SkImage* image = nullptr;
     GrTexture* tex = fDevice->accessRenderTarget()->asTexture();
     if (tex) {
         image = new SkImage_Gpu(info.width(), info.height(), kNeedNewImageUniqueID,
-                                info.alphaType(), tex, sampleCount, budgeted);
+                                info.alphaType(), tex, budgeted);
     }
     if (image) {
         as_IB(image)->initWithProps(this->props());