initial preroll api

BUG=skia:

Review URL: https://codereview.chromium.org/855473002
diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp
index 456e0d4..e6ed113 100644
--- a/src/core/SkBitmapProcShader.cpp
+++ b/src/core/SkBitmapProcShader.cpp
@@ -112,6 +112,12 @@
     return sizeof(BitmapProcShaderContext) + sizeof(SkBitmapProcState);
 }
 
+void SkBitmapProcShader::onPreroll() const {
+    SkBitmap bm(fRawBitmap);
+    bm.lockPixels();
+    bm.unlockPixels();
+}
+
 SkBitmapProcShader::BitmapProcShaderContext::BitmapProcShaderContext(
         const SkBitmapProcShader& shader, const ContextRec& rec, SkBitmapProcState* state)
     : INHERITED(shader, rec)
diff --git a/src/core/SkBitmapProcShader.h b/src/core/SkBitmapProcShader.h
index f73d56f..dc36154 100644
--- a/src/core/SkBitmapProcShader.h
+++ b/src/core/SkBitmapProcShader.h
@@ -57,6 +57,7 @@
 protected:
     void flatten(SkWriteBuffer&) const SK_OVERRIDE;
     Context* onCreateContext(const ContextRec&, void* storage) const SK_OVERRIDE;
+    void onPreroll() const SK_OVERRIDE;
 
     SkBitmap    fRawBitmap;   // experimental for RLE encoding
     uint8_t     fTileModeX, fTileModeY;
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 13b84e7..5b37e08 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -482,9 +482,9 @@
     typedef SkBitmapDevice INHERITED;
 };
 
-SkCanvas::SkCanvas(int width, int height)
+SkCanvas::SkCanvas(int width, int height, const SkSurfaceProps* props)
     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
-    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
+    , fProps(SkSurfacePropsCopyOrDefault(props))
 {
     inc_canvas();
 
diff --git a/src/core/SkPicturePreroll.cpp b/src/core/SkPicturePreroll.cpp
new file mode 100644
index 0000000..b0a4b17
--- /dev/null
+++ b/src/core/SkPicturePreroll.cpp
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkCanvas.h"
+#include "SkPicture.h"
+
+class SkPrerollCanvas : public SkCanvas {
+public:
+    SkPrerollCanvas(int width, int height, const SkSurfaceProps* props)
+        : SkCanvas(width, height, props)
+    {}
+
+protected:
+    void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint& paint) SK_OVERRIDE {
+        this->handlePaint(paint);
+    }
+    
+    void onDrawText(const void*, size_t, SkScalar, SkScalar, const SkPaint& paint) SK_OVERRIDE {
+        this->handlePaint(paint);
+    }
+    
+    void onDrawPosText(const void*, size_t, const SkPoint[], const SkPaint& paint) SK_OVERRIDE {
+        this->handlePaint(paint);
+    }
+    
+    void onDrawPosTextH(const void*, size_t, const SkScalar[], SkScalar,
+                        const SkPaint& paint) SK_OVERRIDE {
+        this->handlePaint(paint);
+    }
+    
+    void onDrawTextOnPath(const void*, size_t, const SkPath&, const SkMatrix*,
+                          const SkPaint& paint) SK_OVERRIDE {
+        this->handlePaint(paint);
+    }
+    
+    void onDrawTextBlob(const SkTextBlob*, SkScalar, SkScalar, const SkPaint& paint) SK_OVERRIDE {
+        this->handlePaint(paint);
+    }
+    
+    void onDrawPatch(const SkPoint[12], const SkColor[4], const SkPoint[4], SkXfermode*,
+                     const SkPaint& paint) SK_OVERRIDE {
+        this->handlePaint(paint);
+    }
+    
+    void onDrawPaint(const SkPaint& paint) SK_OVERRIDE {
+        this->handlePaint(paint);
+    }
+
+    void onDrawRect(const SkRect&, const SkPaint& paint) SK_OVERRIDE {
+        this->handlePaint(paint);
+    }
+
+    void onDrawOval(const SkRect&, const SkPaint& paint) SK_OVERRIDE {
+        this->handlePaint(paint);
+    }
+
+    void onDrawRRect(const SkRRect&, const SkPaint& paint) SK_OVERRIDE {
+        this->handlePaint(paint);
+    }
+
+    void onDrawPoints(PointMode, size_t, const SkPoint[], const SkPaint& paint) {
+        this->handlePaint(paint);
+    }
+
+    void onDrawVertices(VertexMode, int, const SkPoint[], const SkPoint[], const SkColor[],
+                        SkXfermode*, const uint16_t[], int, const SkPaint& paint) SK_OVERRIDE {
+        this->handlePaint(paint);
+    }
+
+    void onDrawPath(const SkPath&, const SkPaint& paint) SK_OVERRIDE {
+        this->handlePaint(paint);
+    }
+
+    void onDrawImage(const SkImage* image, SkScalar, SkScalar, const SkPaint* paint) SK_OVERRIDE {
+        this->handleImage(image);
+        if (paint) {
+            this->handlePaint(*paint);
+        }
+    }
+
+    void onDrawImageRect(const SkImage* image, const SkRect*, const SkRect&,
+                         const SkPaint* paint) SK_OVERRIDE {
+        this->handleImage(image);
+        if (paint) {
+            this->handlePaint(*paint);
+        }
+    }
+
+    void onDrawBitmap(const SkBitmap& bm, SkScalar, SkScalar, const SkPaint* paint) SK_OVERRIDE {
+        this->handleBitmap(bm);
+        if (paint) {
+            this->handlePaint(*paint);
+        }
+    }
+
+    void onDrawBitmapRect(const SkBitmap& bm, const SkRect*, const SkRect&, const SkPaint* paint,
+                          DrawBitmapRectFlags) SK_OVERRIDE {
+        this->handleBitmap(bm);
+        if (paint) {
+            this->handlePaint(*paint);
+        }
+    }
+
+    void onDrawBitmapNine(const SkBitmap& bm, const SkIRect&, const SkRect&,
+                          const SkPaint* paint) SK_OVERRIDE {
+        this->handleBitmap(bm);
+        if (paint) {
+            this->handlePaint(*paint);
+        }
+    }
+
+    void onDrawSprite(const SkBitmap& bm, int, int, const SkPaint* paint) SK_OVERRIDE {
+        this->handleBitmap(bm);
+        if (paint) {
+            this->handlePaint(*paint);
+        }
+    }
+
+private:
+    void handlePaint(const SkPaint& paint) {
+        const SkShader* shader = paint.getShader();
+        if (shader) {
+            shader->preroll();
+        }
+    }
+
+    void handleImage(const SkImage* image) {
+        image->preroll();
+    }
+
+    void handleBitmap(const SkBitmap& bitmap) {
+        SkBitmap bm(bitmap);
+        bm.lockPixels();
+    }
+
+    typedef SkCanvas INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+void SkPicture::preroll(const SkRect* srcBounds, const SkMatrix* initialMatrix,
+                        const SkSurfaceProps* props, void* gpuCacheAccessor) const {
+    SkRect bounds = this->cullRect();
+    if (srcBounds && !bounds.intersect(*srcBounds)) {
+        return;
+    }
+
+    const SkIRect ibounds = bounds.roundOut();
+    if (ibounds.isEmpty()) {
+        return;
+    }
+
+    SkPrerollCanvas canvas(ibounds.width(), ibounds.height(), props);
+
+    canvas.translate(-SkIntToScalar(ibounds.left()), -SkIntToScalar(ibounds.top()));
+    canvas.drawPicture(this, initialMatrix, NULL);
+}
+
diff --git a/src/core/SkPictureShader.cpp b/src/core/SkPictureShader.cpp
index 819a0d0..36b55ca 100644
--- a/src/core/SkPictureShader.cpp
+++ b/src/core/SkPictureShader.cpp
@@ -221,6 +221,10 @@
     return PictureShaderContext::Create(storage, *this, rec, bitmapShader);
 }
 
+void SkPictureShader::onPreroll() const {
+    fPicture->preroll(NULL, NULL, NULL, NULL);
+}
+
 /////////////////////////////////////////////////////////////////////////////////////////
 
 SkShader::Context* SkPictureShader::PictureShaderContext::Create(void* storage,
diff --git a/src/core/SkPictureShader.h b/src/core/SkPictureShader.h
index 8df9f53..7b07b851 100644
--- a/src/core/SkPictureShader.h
+++ b/src/core/SkPictureShader.h
@@ -37,6 +37,7 @@
     SkPictureShader(SkReadBuffer&);
     void flatten(SkWriteBuffer&) const SK_OVERRIDE;
     Context* onCreateContext(const ContextRec&, void* storage) const SK_OVERRIDE;
+    void onPreroll() const SK_OVERRIDE;
 
 private:
     SkPictureShader(const SkPicture*, TileMode, TileMode, const SkMatrix*, const SkRect*);
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
index 1098088..35fff1f 100644
--- a/src/image/SkImage.cpp
+++ b/src/image/SkImage.cpp
@@ -118,6 +118,10 @@
     return as_IB(this)->onNewImage(newWidth, newHeight, subset, quality);
 }
 
+void SkImage::preroll() const {
+    as_IB(this)->onPreroll();
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 static bool raster_canvas_supports(const SkImageInfo& info) {
diff --git a/src/image/SkImage_Base.h b/src/image/SkImage_Base.h
index 512c80c..ca0559f 100644
--- a/src/image/SkImage_Base.h
+++ b/src/image/SkImage_Base.h
@@ -63,6 +63,8 @@
     virtual SkImage* onNewImage(int newWidth, int newHeight, const SkIRect* subset,
                                 SkFilterQuality) const;
 
+    virtual void onPreroll() const {}
+
 private:
     const SkSurfaceProps fProps;
 
diff --git a/src/image/SkImage_Raster.cpp b/src/image/SkImage_Raster.cpp
index 1dd57d6..940d532 100644
--- a/src/image/SkImage_Raster.cpp
+++ b/src/image/SkImage_Raster.cpp
@@ -58,6 +58,7 @@
     bool onReadPixels(const SkImageInfo&, void*, size_t, int srcX, int srcY) const SK_OVERRIDE;
     const void* onPeekPixels(SkImageInfo*, size_t* /*rowBytes*/) const SK_OVERRIDE;
     bool getROPixels(SkBitmap*) const SK_OVERRIDE;
+    void onPreroll() const SK_OVERRIDE;
 
     // exposed for SkSurface_Raster via SkNewImageFromPixelRef
     SkImage_Raster(const SkImageInfo&, SkPixelRef*, size_t rowBytes, const SkSurfaceProps*);
@@ -154,6 +155,12 @@
     return true;
 }
 
+void SkImage_Raster::onPreroll() const {
+    SkBitmap bm(fBitmap);
+    bm.lockPixels();
+    bm.unlockPixels();
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 SkImage* SkImage::NewRasterCopy(const SkImageInfo& info, const void* pixels, size_t rowBytes) {
@@ -208,3 +215,4 @@
 bool SkImage_Raster::isOpaque() const {
     return fBitmap.isOpaque();
 }
+