remove SkCanvas::createCompatibleDevice, and add SkCanvas::newSurface

BUG=skia:
R=bsalomon@google.com

Review URL: https://codereview.chromium.org/154163002

git-svn-id: http://skia.googlecode.com/svn/trunk@13319 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/expectations/gm/ignored-tests.txt b/expectations/gm/ignored-tests.txt
index 2e3afd7..b6c9107 100644
--- a/expectations/gm/ignored-tests.txt
+++ b/expectations/gm/ignored-tests.txt
@@ -35,3 +35,8 @@
 
 # Added by bsalomon for skbug.com/2051, https://codereview.chromium.org/151523005
 filltypespersp
+
+# Need to rebaseline all platforms, as the content was changed to remove
+# deprecated calling pattern.
+# https://codereview.chromium.org/154163002/
+extractbitmap
diff --git a/gm/extractbitmap.cpp b/gm/extractbitmap.cpp
index efc5d35..6e7409d 100644
--- a/gm/extractbitmap.cpp
+++ b/gm/extractbitmap.cpp
@@ -1,15 +1,16 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+
 #include "gm.h"
 #include "SkBitmap.h"
 #include "SkCanvas.h"
 #include "SkDevice.h"
 #include "SkString.h"
+#include "SkSurface.h"
 
 namespace skiagm {
 
@@ -71,24 +72,6 @@
             canvas->translate(0, SkIntToScalar(bitmap.height() + 20));
             canvas->drawBitmap(subset, 0, 0);
         }
-
-        // Now do the same but with a device bitmap as source image
-        SkAutoTUnref<SkBaseDevice> secondDevice(canvas->createCompatibleDevice(
-            SkBitmap::kARGB_8888_Config, bitmap.width(),
-            bitmap.height(), true));
-        SkCanvas secondCanvas(secondDevice.get());
-        secondCanvas.writePixels(bitmap, 0, 0);
-
-        SkBitmap deviceBitmap = secondDevice->accessBitmap(false);
-        SkBitmap deviceSubset;
-        deviceBitmap.extractSubset(&deviceSubset,
-             SkIRect::MakeXYWH(x, y, x, y));
-
-        canvas->translate(SkIntToScalar(120), SkIntToScalar(0));
-
-        canvas->drawBitmap(deviceBitmap, 0, 0);
-        canvas->drawBitmap(deviceSubset, 0, 0);
-
     }
 
 private:
diff --git a/include/core/SkBitmapDevice.h b/include/core/SkBitmapDevice.h
index a9208e2..945ffbf 100644
--- a/include/core/SkBitmapDevice.h
+++ b/include/core/SkBitmapDevice.h
@@ -277,6 +277,8 @@
      */
     virtual void flush() SK_OVERRIDE {}
 
+    virtual SkSurface* newSurface(const SkImageInfo&) SK_OVERRIDE;
+
     SkBitmap    fBitmap;
 
     typedef SkBaseDevice INHERITED;
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index c98ad99..af42c12 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2006 The Android Open Source Project
  *
@@ -6,7 +5,6 @@
  * found in the LICENSE file.
  */
 
-
 #ifndef SkCanvas_DEFINED
 #define SkCanvas_DEFINED
 
@@ -20,6 +18,8 @@
 #include "SkRegion.h"
 #include "SkXfermode.h"
 
+//#define SK_SUPPORT_LEGACY_CANVAS_CREATECOMPATIBLEDEVICE
+
 class SkBounder;
 class SkBaseDevice;
 class SkDraw;
@@ -27,6 +27,7 @@
 class SkMetaData;
 class SkPicture;
 class SkRRect;
+class SkSurface;
 class SkSurface_Base;
 class GrContext;
 
@@ -112,6 +113,7 @@
      */
     SkBaseDevice* getTopDevice(bool updateMatrixClip = false) const;
 
+#ifdef SK_SUPPORT_LEGACY_CANVAS_CREATECOMPATIBLEDEVICE
     /**
      *  Shortcut for getDevice()->createCompatibleDevice(...).
      *  If getDevice() == NULL, this method does nothing, and returns NULL.
@@ -119,6 +121,13 @@
     SkBaseDevice* createCompatibleDevice(SkBitmap::Config config,
                                          int width, int height,
                                          bool isOpaque);
+#endif
+
+    /**
+     *  Create a new surface matching the specified info, one that attempts to
+     *  be maximally compatible when used with this canvas.
+     */
+    SkSurface* newSurface(const SkImageInfo&);
 
     /**
      * Return the GPU context of the device that is associated with the canvas.
@@ -1019,6 +1028,9 @@
     };
 
 protected:
+    // default impl defers to getDevice()->newSurface(info)
+    virtual SkSurface* onNewSurface(const SkImageInfo&);
+
     // Returns the canvas to be used by DrawIter. Default implementation
     // returns this. Subclasses that encapsulate an indirect canvas may
     // need to overload this method. The impl must keep track of this, as it
diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h
index 250a6a3..7c83f44 100644
--- a/include/core/SkDevice.h
+++ b/include/core/SkDevice.h
@@ -367,6 +367,9 @@
     static const SkCanvas::Config8888 kPMColorAlias;
 
 protected:
+    // default impl returns NULL
+    virtual SkSurface* newSurface(const SkImageInfo&);
+
     /**
      *  Leaky properties are those which the device should be applying but it isn't.
      *  These properties will be applied by the draw, when and as it can.
@@ -382,6 +385,7 @@
     friend class SkDrawIter;
     friend class SkDeviceFilteredPaint;
     friend class SkDeviceImageFilterProxy;
+    friend class DeferredDevice;    // for newSurface
 
     friend class SkSurface_Raster;
 
diff --git a/include/gpu/SkGpuDevice.h b/include/gpu/SkGpuDevice.h
index e791ca4..151a6dc 100644
--- a/include/gpu/SkGpuDevice.h
+++ b/include/gpu/SkGpuDevice.h
@@ -169,6 +169,8 @@
                                                    bool isOpaque,
                                                    Usage usage) SK_OVERRIDE;
 
+    virtual SkSurface* newSurface(const SkImageInfo&) SK_OVERRIDE;
+
     // sets the render target, clip, and matrix on GrContext. Use forceIdenity to override
     // SkDraw's matrix and draw in device coords.
     void prepareDraw(const SkDraw&, bool forceIdentity);
diff --git a/samplecode/SampleTextureDomain.cpp b/samplecode/SampleTextureDomain.cpp
index 16e7a16..854df6e 100644
--- a/samplecode/SampleTextureDomain.cpp
+++ b/samplecode/SampleTextureDomain.cpp
@@ -9,7 +9,7 @@
 #include "SkBlurMask.h"
 #include "SkBlurMaskFilter.h"
 #include "SkCanvas.h"
-#include "SkDevice.h"
+#include "SkSurface.h"
 
 static SkBitmap make_bitmap() {
     SkBitmap bm;
@@ -45,7 +45,7 @@
     }
 
     virtual void onDrawContent(SkCanvas* canvas) {
-        SkIRect srcRect;
+        SkRect srcRect;
         SkRect dstRect;
         SkPaint paint;
         paint.setFilterLevel(SkPaint::kLow_FilterLevel);
@@ -53,54 +53,53 @@
         // Test that bitmap draws from malloc-backed bitmaps respect
         // the constrained texture domain.
         srcRect.setXYWH(1, 1, 3, 3);
-        dstRect.setXYWH(5.0f, 5.0f, 305.0f, 305.0f);
-        canvas->drawBitmapRect(fBM, &srcRect, dstRect, &paint);
+        dstRect.setXYWH(5, 5, 305, 305);
+        canvas->drawBitmapRectToRect(fBM, &srcRect, dstRect, &paint);
 
         // Test that bitmap draws across separate devices also respect
         // the constrainted texture domain.
         // Note:  GPU-backed bitmaps follow a different rendering path
         // when copying from one GPU device to another.
-        SkAutoTUnref<SkBaseDevice> secondDevice(canvas->createCompatibleDevice(
-                SkBitmap::kARGB_8888_Config, 5, 5, true));
-        SkCanvas secondCanvas(secondDevice.get());
+        SkImageInfo info = SkImageInfo::MakeN32(5, 5, kOpaque_SkAlphaType);
+        SkAutoTUnref<SkSurface> surface(canvas->newSurface(info));
 
         srcRect.setXYWH(1, 1, 3, 3);
-        dstRect.setXYWH(1.0f, 1.0f, 3.0f, 3.0f);
-        secondCanvas.drawBitmapRect(fBM, &srcRect, dstRect, &paint);
+        dstRect.setXYWH(1, 1, 3, 3);
+        surface->getCanvas()->drawBitmapRectToRect(fBM, &srcRect, dstRect,
+                                                   &paint);
 
-        SkBitmap deviceBitmap = secondDevice->accessBitmap(false);
+        SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
 
         srcRect.setXYWH(1, 1, 3, 3);
-        dstRect.setXYWH(405.0f, 5.0f, 305.0f, 305.0f);
-        canvas->drawBitmapRect(deviceBitmap, &srcRect, dstRect, &paint);
+        dstRect.setXYWH(405, 5, 305, 305);
+        image->draw(canvas, &srcRect, dstRect, &paint);
 
         // Test that bitmap blurring using a subrect
         // renders correctly
         srcRect.setXYWH(1, 1, 3, 3);
-        dstRect.setXYWH(5.0f, 405.0f, 305.0f, 305.0f);
+        dstRect.setXYWH(5, 405, 305, 305);
         SkMaskFilter* mf = SkBlurMaskFilter::Create(
             SkBlurMaskFilter::kNormal_BlurStyle,
             SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(5)),
             SkBlurMaskFilter::kHighQuality_BlurFlag |
             SkBlurMaskFilter::kIgnoreTransform_BlurFlag);
         paint.setMaskFilter(mf)->unref();
-        canvas->drawBitmapRect(deviceBitmap, &srcRect, dstRect, &paint);
+        image->draw(canvas, &srcRect, dstRect, &paint);
 
         // Blur and a rotation + NULL src rect
         // This should not trigger the texture domain code
         // but it will test a code path in SkGpuDevice::drawBitmap
         // that handles blurs with rects transformed to non-
         // orthogonal rects. It also tests the NULL src rect handling
-    mf = SkBlurMaskFilter::Create(
-            SkBlurMaskFilter::kNormal_BlurStyle,
-            SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(5)),
-            SkBlurMaskFilter::kHighQuality_BlurFlag);
+        mf = SkBlurMaskFilter::Create(SkBlurMaskFilter::kNormal_BlurStyle,
+                                      SkBlurMask::ConvertRadiusToSigma(5),
+                                      SkBlurMaskFilter::kHighQuality_BlurFlag);
         paint.setMaskFilter(mf)->unref();
 
-        dstRect.setXYWH(-150.0f, -150.0f, 300.0f, 300.0f);
+        dstRect.setXYWH(-150, -150, 300, 300);
         canvas->translate(550, 550);
         canvas->rotate(45);
-        canvas->drawBitmapRect(fBM, NULL, dstRect, &paint);
+        canvas->drawBitmapRectToRect(fBM, NULL, dstRect, &paint);
     }
 private:
     typedef SkView INHERITED;
diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp
index 4b4f453..5e70b1a 100644
--- a/src/core/SkBitmapDevice.cpp
+++ b/src/core/SkBitmapDevice.cpp
@@ -10,6 +10,7 @@
 #include "SkDraw.h"
 #include "SkRasterClip.h"
 #include "SkShader.h"
+#include "SkSurface.h"
 
 #define CHECK_FOR_ANNOTATION(paint) \
     do { if (paint.getAnnotation()) { return; } } while (0)
@@ -381,6 +382,10 @@
     draw.drawSprite(src, x, y, paint);
 }
 
+SkSurface* SkBitmapDevice::newSurface(const SkImageInfo& info) {
+    return SkSurface::NewRaster(info);
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 bool SkBitmapDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 08b09e8..6f4e88d 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -832,6 +832,26 @@
     return this->internalSaveLayer(bounds, paint, flags, false);
 }
 
+static SkBaseDevice* createCompatibleDevice(SkCanvas* canvas,
+                                            SkBitmap::Config config,
+                                            int width, int height,
+                                            bool isOpaque) {
+    SkBaseDevice* device = canvas->getDevice();
+    if (device) {
+        return device->createCompatibleDevice(config, width, height, isOpaque);
+    } else {
+        return NULL;
+    }
+}
+
+#ifdef SK_SUPPORT_LEGACY_CANVAS_CREATECOMPATIBLEDEVICE
+SkBaseDevice* SkCanvas::createCompatibleDevice(SkBitmap::Config config,
+                                               int width, int height,
+                                               bool isOpaque) {
+    return createCompatibleDevice(this, config, width, height, isOpaque);
+}
+#endif
+
 int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint,
                                 SaveFlags flags, bool justForImageFilter) {
     // do this before we create the layer. We don't call the public save() since
@@ -864,8 +884,8 @@
 
     SkBaseDevice* device;
     if (paint && paint->getImageFilter()) {
-        device = this->createCompatibleDevice(config, ir.width(), ir.height(),
-                                              isOpaque);
+        device = createCompatibleDevice(this, config, ir.width(), ir.height(),
+                                        isOpaque);
     } else {
         device = this->createLayerDevice(config, ir.width(), ir.height(),
                                          isOpaque);
@@ -964,6 +984,15 @@
     return fSaveLayerCount > 0;
 }
 
+SkSurface* SkCanvas::newSurface(const SkImageInfo& info) {
+    return this->onNewSurface(info);
+}
+
+SkSurface* SkCanvas::onNewSurface(const SkImageInfo& info) {
+    SkBaseDevice* dev = this->getDevice();
+    return dev ? dev->newSurface(info) : NULL;
+}
+
 /////////////////////////////////////////////////////////////////////////////
 
 // can't draw it if its empty, or its too big for a fixed-point width or height
@@ -1548,17 +1577,6 @@
     }
 }
 
-SkBaseDevice* SkCanvas::createCompatibleDevice(SkBitmap::Config config,
-                                           int width, int height,
-                                           bool isOpaque) {
-    SkBaseDevice* device = this->getDevice();
-    if (device) {
-        return device->createCompatibleDevice(config, width, height, isOpaque);
-    } else {
-        return NULL;
-    }
-}
-
 GrContext* SkCanvas::getGrContext() {
 #if SK_SUPPORT_GPU
     SkBaseDevice* device = this->getTopDevice();
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index c08ae26..9ce8b6b 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
@@ -18,6 +17,7 @@
 #endif
 
 ///////////////////////////////////////////////////////////////////////////////
+
 SkBaseDevice::SkBaseDevice()
     : fLeakyProperties(SkDeviceProperties::MakeDefault())
 #ifdef SK_DEBUG
@@ -115,3 +115,5 @@
     }
     return result;
 }
+
+SkSurface* SkBaseDevice::newSurface(const SkImageInfo&) { return NULL; }
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index 3bf9851..5ce35d6 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -1,10 +1,10 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+
 #include "SkPictureRecord.h"
 #include "SkTSearch.h"
 #include "SkPixelRef.h"
@@ -12,6 +12,7 @@
 #include "SkBBoxHierarchy.h"
 #include "SkDevice.h"
 #include "SkPictureStateTree.h"
+#include "SkSurface.h"
 
 #define HEAP_BLOCK_SIZE 4096
 
@@ -1316,6 +1317,10 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+SkSurface* SkPictureRecord::onNewSurface(const SkImageInfo& info) {
+    return SkSurface::NewPicture(info.fWidth, info.fHeight);
+}
+
 void SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
     const int index = fBitmapHeap->insert(bitmap);
     // In debug builds, a bad return value from insert() will crash, allowing for debugging. In
diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h
index 3832516..6d14c62 100644
--- a/src/core/SkPictureRecord.h
+++ b/src/core/SkPictureRecord.h
@@ -1,10 +1,10 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+
 #ifndef SkPictureRecord_DEFINED
 #define SkPictureRecord_DEFINED
 
@@ -215,6 +215,8 @@
 #endif
 
 protected:
+    virtual SkSurface* onNewSurface(const SkImageInfo&) SK_OVERRIDE;
+
     // Return fontmetrics.fTop,fBottom in topbot[0,1], after they have been
     // tweaked by paint.computeFastBounds().
     static void ComputeFontMetricsTopBottom(const SkPaint& paint, SkScalar topbot[2]);
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index da56009..8c272f9 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -27,6 +27,7 @@
 #include "SkPathEffect.h"
 #include "SkRRect.h"
 #include "SkStroke.h"
+#include "SkSurface.h"
 #include "SkTLazy.h"
 #include "SkUtils.h"
 #include "SkErrorInternals.h"
@@ -1913,6 +1914,10 @@
     }
 }
 
+SkSurface* SkGpuDevice::newSurface(const SkImageInfo& info) {
+    return SkSurface::NewRenderTarget(fContext, info, fRenderTarget->numSamples());
+}
+
 SkGpuDevice::SkGpuDevice(GrContext* context,
                          GrTexture* texture,
                          bool needClear)
diff --git a/src/utils/SkDeferredCanvas.cpp b/src/utils/SkDeferredCanvas.cpp
index 1cb6d37..efc6546 100644
--- a/src/utils/SkDeferredCanvas.cpp
+++ b/src/utils/SkDeferredCanvas.cpp
@@ -173,6 +173,8 @@
     virtual void writePixels(const SkBitmap& bitmap, int x, int y,
                                 SkCanvas::Config8888 config8888) SK_OVERRIDE;
 
+    virtual SkSurface* newSurface(const SkImageInfo&) SK_OVERRIDE;
+
 protected:
     virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE;
     virtual bool onReadPixels(const SkBitmap& bitmap,
@@ -495,6 +497,10 @@
     return immediateDevice()->createCompatibleDevice(config, width, height, isOpaque);
 }
 
+SkSurface* DeferredDevice::newSurface(const SkImageInfo& info) {
+    return this->immediateDevice()->newSurface(info);
+}
+
 bool DeferredDevice::onReadPixels(
     const SkBitmap& bitmap, int x, int y, SkCanvas::Config8888 config8888) {
     this->flushPendingCommands(kNormal_PlaybackMode);
diff --git a/tests/DeferredCanvasTest.cpp b/tests/DeferredCanvasTest.cpp
index 81f19b1..a40c667 100644
--- a/tests/DeferredCanvasTest.cpp
+++ b/tests/DeferredCanvasTest.cpp
@@ -825,14 +825,14 @@
     NotificationCounter notificationCounter;
     canvas->setNotificationClient(&notificationCounter);
 
-    SkAutoTUnref<SkBaseDevice> secondaryDevice(canvas->createCompatibleDevice(
-        SkBitmap::kARGB_8888_Config, 10, 10, false));
-    SkCanvas secondaryCanvas(secondaryDevice.get());
+    SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10);
+    SkAutoTUnref<SkSurface> secondarySurface(canvas->newSurface(info));
+
     SkRect rect = SkRect::MakeWH(5, 5);
     SkPaint paint;
     // After spawning a compatible canvas:
     // 1) Verify that secondary canvas is usable and does not report to the notification client.
-    secondaryCanvas.drawRect(rect, paint);
+    surface->getCanvas()->drawRect(rect, paint);
     REPORTER_ASSERT(reporter, notificationCounter.fStorageAllocatedChangedCount == 0);
     // 2) Verify that original canvas is usable and still reports to the notification client.
     canvas->drawRect(rect, paint);