Try out scalar picture sizes

This paves the way for removing the 'fTile' parameter from SkPictureShader (although that should be a different CL). If we like this we could also move to providing an entire cull SkRect.

R=reed@google.com, mtklein@google.com, fmalita@google.com, fmalita@chromium.org

Author: robertphillips@google.com

Review URL: https://codereview.chromium.org/513983002
diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp
index f2bf30a..3dcd9db 100644
--- a/bench/nanobench.cpp
+++ b/bench/nanobench.cpp
@@ -494,7 +494,9 @@
                     };
                     SkTileGridFactory factory(info);
                     SkPictureRecorder recorder;
-                    pic->draw(recorder.beginRecording(pic->width(), pic->height(), &factory));
+                    pic->draw(recorder.beginRecording(pic->cullRect().width(), 
+                                                      pic->cullRect().height(), 
+                                                      &factory));
                     pic.reset(recorder.endRecording());
                 }
 
diff --git a/debugger/QT/SkGLWidget.cpp b/debugger/QT/SkGLWidget.cpp
index 602dc24..dece641 100644
--- a/debugger/QT/SkGLWidget.cpp
+++ b/debugger/QT/SkGLWidget.cpp
@@ -68,7 +68,7 @@
         fGpuDevice = SkGpuDevice::Create(curRenderTarget);
         fCanvas = new SkCanvas(fGpuDevice);
     }
-    fDebugger->resize(w, h);
+    fDebugger->setWindowSize(w, h);
     draw();
 }
 
diff --git a/debugger/QT/SkRasterWidget.cpp b/debugger/QT/SkRasterWidget.cpp
index 705fdf0..ad05d39 100644
--- a/debugger/QT/SkRasterWidget.cpp
+++ b/debugger/QT/SkRasterWidget.cpp
@@ -29,7 +29,7 @@
     SkSafeUnref(fDevice);
     fDevice = new SkBitmapDevice(fBitmap);
     fCanvas = new SkCanvas(fDevice);
-    fDebugger->resize(event->size().width(), event->size().height());
+    fDebugger->setWindowSize(event->size().width(), event->size().height());
     this->update();
 }
 
diff --git a/debugger/SkDebugger.cpp b/debugger/SkDebugger.cpp
index af6900c..fda8f9a 100644
--- a/debugger/SkDebugger.cpp
+++ b/debugger/SkDebugger.cpp
@@ -13,10 +13,8 @@
 
 SkDebugger::SkDebugger() {
     // Create this some other dynamic way?
-    fDebugCanvas = new SkDebugCanvas(100, 100);
+    fDebugCanvas = new SkDebugCanvas(0, 0);
     fPicture = NULL;
-    fPictureWidth = 0;
-    fPictureHeight = 0;
     fIndex = 0;
 }
 
@@ -27,23 +25,23 @@
 }
 
 void SkDebugger::loadPicture(SkPicture* picture) {
-    fPictureWidth = picture->width();
-    fPictureHeight = picture->height();
+    SkRefCnt_SafeAssign(fPicture, picture);
+
     delete fDebugCanvas;
-    fDebugCanvas = new SkDebugCanvas(fPictureWidth, fPictureHeight);
-    fDebugCanvas->setBounds(fPictureWidth, fPictureHeight);
+    fDebugCanvas = new SkDebugCanvas(SkScalarCeilToInt(this->pictureCull().width()), 
+                                     SkScalarCeilToInt(this->pictureCull().height()));
     fDebugCanvas->setPicture(picture);
     picture->draw(fDebugCanvas);
     fDebugCanvas->setPicture(NULL);
     fIndex = fDebugCanvas->getSize() - 1;
-    SkRefCnt_SafeAssign(fPicture, picture);
 }
 
 SkPicture* SkDebugger::copyPicture() {
     // We can't just call clone here since we want to removed the "deleted"
     // commands. Playing back will strip those out.
     SkPictureRecorder recorder;
-    SkCanvas* canvas = recorder.beginRecording(fPictureWidth, fPictureHeight, NULL, 0);
+    SkCanvas* canvas = recorder.beginRecording(this->pictureCull().width(), 
+                                               this->pictureCull().height());
 
     bool vizMode = fDebugCanvas->getMegaVizMode();
     fDebugCanvas->setMegaVizMode(false);
@@ -143,13 +141,15 @@
     totalStr.append("<br/>");
     overview->insert(0, totalStr);
 
+    overview->append("<br/>SkPicture L: ");
+    overview->appendScalar(this->pictureCull().fLeft);
+    overview->append(" T: ");
+    overview->appendScalar(this->pictureCull().fTop);
+    overview->append(" R: ");
+    overview->appendScalar(this->pictureCull().fRight);
+    overview->append(" B: ");
+    overview->appendScalar(this->pictureCull().fBottom);
     overview->append("<br/>");
-    overview->append("SkPicture Width: ");
-    overview->appendS32(pictureWidth());
-    overview->append("px<br/>");
-    overview->append("SkPicture Height: ");
-    overview->appendS32(pictureHeight());
-    overview->append("px");
 }
 
 void SkDebugger::getClipStackText(SkString* clipStack) {
diff --git a/debugger/SkDebugger.h b/debugger/SkDebugger.h
index ffb2953..9ad21e2 100644
--- a/debugger/SkDebugger.h
+++ b/debugger/SkDebugger.h
@@ -60,9 +60,7 @@
         fDebugCanvas->toggleFilter(on);
     }
 
-    void resize(int width, int height) {
-        fDebugCanvas->setBounds(width, height);
-    }
+    void setWindowSize(int width, int height) { fDebugCanvas->setWindowSize(width, height); }
 
     void loadPicture(SkPicture* picture);
 
@@ -93,12 +91,8 @@
         return fDebugCanvas->getCurrentClip();
     }
 
-    int pictureHeight() {
-        return fPictureHeight;
-    }
-
-    int pictureWidth() {
-        return fPictureWidth;
+    SkRect pictureCull() const   { 
+        return NULL == fPicture ? SkRect::MakeEmpty() : fPicture->cullRect();
     }
 
     int index() {
@@ -138,8 +132,6 @@
     SkDebugCanvas* fDebugCanvas;
     SkPicture* fPicture;
 
-    int fPictureWidth;
-    int fPictureHeight;
     int fIndex;
 };
 
diff --git a/dm/DMPDFTask.cpp b/dm/DMPDFTask.cpp
index 81fd307..7d1fa59 100644
--- a/dm/DMPDFTask.cpp
+++ b/dm/DMPDFTask.cpp
@@ -76,7 +76,7 @@
         fGM->draw(pdf.canvas());
         pdfData.reset(pdf.end());
     } else {
-        SinglePagePDF pdf(SkIntToScalar(fPicture->width()), SkIntToScalar(fPicture->height()));
+        SinglePagePDF pdf(fPicture->cullRect().width(), fPicture->cullRect().height());
         fPicture->draw(pdf.canvas());
         pdfData.reset(pdf.end());
     }
diff --git a/dm/DMSKPTask.cpp b/dm/DMSKPTask.cpp
index 765fe10..ece7e9a 100644
--- a/dm/DMSKPTask.cpp
+++ b/dm/DMSKPTask.cpp
@@ -14,8 +14,8 @@
     : CpuTask(r, tr), fPicture(SkRef(pic)), fName(FileToTaskName(filename)) {}
 
 void SKPTask::draw() {
-    const int width  = SkTMin(fPicture->width(),  FLAGS_skpMaxWidth),
-              height = SkTMin(fPicture->height(), FLAGS_skpMaxHeight);
+    const int width  = SkTMin(SkScalarCeilToInt(fPicture->cullRect().width()),  FLAGS_skpMaxWidth),
+              height = SkTMin(SkScalarCeilToInt(fPicture->cullRect().height()), FLAGS_skpMaxHeight);
     SkBitmap bitmap;
     AllocatePixels(kN32_SkColorType, width, height, &bitmap);
     DrawPicture(*fPicture, &bitmap);
diff --git a/dm/DMUtil.cpp b/dm/DMUtil.cpp
index 33af18e..19b1c0f 100644
--- a/dm/DMUtil.cpp
+++ b/dm/DMUtil.cpp
@@ -21,8 +21,8 @@
 }
 
 SkPicture* RecordPicture(skiagm::GM* gm, SkBBHFactory* factory, bool skr) {
-    const int w = gm->getISize().width(),
-              h = gm->getISize().height();
+    const SkScalar w = SkIntToScalar(gm->getISize().width()),
+                   h = SkIntToScalar(gm->getISize().height());
     SkPictureRecorder recorder;
 
     SkCanvas* canvas = skr ? recorder.EXPERIMENTAL_beginRecording(w, h, factory)
diff --git a/experimental/nanomsg/picture_demo.cpp b/experimental/nanomsg/picture_demo.cpp
index 5a3ebdc..f04a96e 100644
--- a/experimental/nanomsg/picture_demo.cpp
+++ b/experimental/nanomsg/picture_demo.cpp
@@ -82,9 +82,9 @@
     SkAutoTUnref<SkPicture> picture(SkPicture::CreateFromStream(&stream));
 
     PictureHeader header;
-    SkRandom rand(picture->width() * picture->height());
-    SkScalar r = rand.nextRangeScalar(0, picture->width()),
-             b = rand.nextRangeScalar(0, picture->height()),
+    SkRandom rand(picture->cullRect().width() * picture->cullRect().height());
+    SkScalar r = rand.nextRangeScalar(0, picture->cullRect().width()),
+             b = rand.nextRangeScalar(0, picture->cullRect().height()),
              l = rand.nextRangeScalar(0, r),
              t = rand.nextRangeScalar(0, b);
     header.clip.setLTRB(l,t,r,b);
diff --git a/gm/distantclip.cpp b/gm/distantclip.cpp
index 9c44140..0f89559 100644
--- a/gm/distantclip.cpp
+++ b/gm/distantclip.cpp
@@ -27,37 +27,33 @@
     SkISize onISize() { return SkISize::Make(100, 100); }
 
     virtual void onDraw(SkCanvas* canvas) {
-        int offset = 35000;
-        int extents = 1000;
+        static const SkScalar kOffset = 35000.0f;
+        static const SkScalar kExtents = 1000.0f;
 
         SkPictureRecorder recorder;
         // We record a picture of huge vertical extents in which we clear the canvas to red, create
         // a 'extents' by 'extents' round rect clip at a vertical offset of 'offset', then draw
         // green into that.
-        SkCanvas* rec = recorder.beginRecording(100, offset + extents, NULL, 0);
-        rec->drawColor(0xffff0000);
+        SkCanvas* rec = recorder.beginRecording(kExtents, kOffset + kExtents, NULL, 0);
+        rec->drawColor(SK_ColorRED);
         rec->save();
-        SkRect r = {
-            SkIntToScalar(-extents),
-            SkIntToScalar(offset - extents),
-            SkIntToScalar(extents),
-            SkIntToScalar(offset + extents)
-        };
+        SkRect r = SkRect::MakeXYWH(-kExtents, kOffset - kExtents, 2 * kExtents, 2 * kExtents);
         SkPath p;
         p.addRoundRect(r, 5, 5);
         rec->clipPath(p, SkRegion::kIntersect_Op, true);
-        rec->drawColor(0xff00ff00);
+        rec->drawColor(SK_ColorGREEN);
         rec->restore();
         SkAutoTUnref<SkPicture> pict(recorder.endRecording());
 
         // Next we play that picture into another picture of the same size.
-        pict->draw(recorder.beginRecording(100, offset + extents, NULL, 0));
+        pict->draw(recorder.beginRecording(pict->cullRect().width(), 
+                                           pict->cullRect().height(), 
+                                           NULL, 0));
         SkAutoTUnref<SkPicture> pict2(recorder.endRecording());
 
         // Finally we play the part of that second picture that should be green into the canvas.
         canvas->save();
-        canvas->translate(SkIntToScalar(extents / 2),
-                          SkIntToScalar(-(offset - extents / 2)));
+        canvas->translate(kExtents / 2, -(kOffset - kExtents / 2));
         pict2->draw(canvas);
         canvas->restore();
 
diff --git a/gm/gmmain.cpp b/gm/gmmain.cpp
index cf9e25b..5d6481c 100644
--- a/gm/gmmain.cpp
+++ b/gm/gmmain.cpp
@@ -1011,8 +1011,8 @@
 
     static SkPicture* generate_new_picture(GM* gm, BbhType bbhType, uint32_t recordFlags,
                                            SkScalar scale = SK_Scalar1) {
-        int width = SkScalarCeilToInt(SkScalarMul(SkIntToScalar(gm->getISize().width()), scale));
-        int height = SkScalarCeilToInt(SkScalarMul(SkIntToScalar(gm->getISize().height()), scale));
+        SkScalar width = SkScalarMul(SkIntToScalar(gm->getISize().width()), scale);
+        SkScalar height = SkScalarMul(SkIntToScalar(gm->getISize().height()), scale);
 
         SkAutoTDelete<SkBBHFactory> factory;
         if (kTileGrid_BbhType == bbhType) {
diff --git a/gm/multipicturedraw.cpp b/gm/multipicturedraw.cpp
index 2da1ab6..11756a7 100644
--- a/gm/multipicturedraw.cpp
+++ b/gm/multipicturedraw.cpp
@@ -52,7 +52,8 @@
 
     SkPictureRecorder recorder;
 
-    SkCanvas* canvas = recorder.beginRecording(kPicWidth, kPicHeight);
+    SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kPicWidth), 
+                                               SkIntToScalar(kPicHeight));
 
     SkScalar xPos, yPos = 0;
 
@@ -111,7 +112,7 @@
 static void rect_clip(SkCanvas* canvas, const SkPicture* pictures[2]) {
     canvas->drawPicture(pictures[0]);
 
-    SkRect rect = SkRect::MakeWH(SkIntToScalar(kPicWidth), SkIntToScalar(kPicHeight));
+    SkRect rect = pictures[0]->cullRect();
     rect.inset(kInset, kInset);
 
     canvas->clipRect(rect);
@@ -123,7 +124,7 @@
 static void rrect_clip(SkCanvas* canvas, const SkPicture* pictures[2]) {
     canvas->drawPicture(pictures[0]);
 
-    SkRect rect = SkRect::MakeWH(SkIntToScalar(kPicWidth), SkIntToScalar(kPicHeight));
+    SkRect rect = pictures[0]->cullRect();
     rect.inset(kInset, kInset);
         
     SkRRect rrect;
@@ -175,7 +176,8 @@
     {
         SkPictureRecorder recorder;
 
-        SkCanvas* pictureCanvas = recorder.beginRecording(kPicWidth, kPicHeight);
+        SkCanvas* pictureCanvas = recorder.beginRecording(SkIntToScalar(kPicWidth), 
+                                                          SkIntToScalar(kPicHeight));
 
         (*pfGen)(pictureCanvas, pictures);
 
@@ -299,7 +301,7 @@
             fPictures[1] = make_picture(SK_ColorGRAY);
         }
 
-        virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE{
+        virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
             SkMultiPictureDraw mpd;
             SkTArray<ComposeStep> composeSteps;
 
@@ -320,9 +322,9 @@
             }
         }
 
-        virtual SkISize onISize() SK_OVERRIDE{ return SkISize::Make(kPicWidth, kPicHeight); }
+        virtual SkISize onISize() SK_OVERRIDE { return SkISize::Make(kPicWidth, kPicHeight); }
 
-        virtual SkString onShortName() SK_OVERRIDE{
+        virtual SkString onShortName() SK_OVERRIDE {
             static const char* gContentNames[] = { 
                 "noclip", "rectclip", "rrectclip", "pathclip", "invpathclip" 
             };
diff --git a/gm/optimizations.cpp b/gm/optimizations.cpp
index a33f457..00be04c 100644
--- a/gm/optimizations.cpp
+++ b/gm/optimizations.cpp
@@ -17,8 +17,8 @@
 // heavy-weight operation since we are drawing the picture into a debug canvas
 // to extract the commands.
 static bool check_pattern(SkPicture& input, const SkTDArray<DrawType> &pattern) {
-    SkDebugCanvas debugCanvas(input.width(), input.height());
-    debugCanvas.setBounds(input.width(), input.height());
+    SkDebugCanvas debugCanvas(SkScalarCeilToInt(input.cullRect().width()), 
+                              SkScalarCeilToInt(input.cullRect().height()));
     input.draw(&debugCanvas);
 
     if (pattern.count() != debugCanvas.getSize()) {
@@ -340,7 +340,7 @@
         };
 
         SkTDArray<DrawType> prePattern, postPattern;
-        int xPos = 0, yPos = 0;
+        SkScalar xPos = 0, yPos = 0;
 
         for (size_t i = 0; i < SK_ARRAY_COUNT(gOpts); ++i) {
             SkAutoTUnref<SkPicture> pre((*gOpts[i])(&prePattern, &postPattern, fCheckerboard));
@@ -351,16 +351,18 @@
             }
 
             canvas->save();
-                canvas->translate(SkIntToScalar(xPos), SkIntToScalar(yPos));
+                canvas->translate(xPos, yPos);
                 pre->draw(canvas);
-                xPos += pre->width();
+                xPos += pre->cullRect().width();
             canvas->restore();
 
             // re-render the 'pre' picture and thus 'apply' the optimization
             SkPictureRecorder recorder;
 
             SkCanvas* recordCanvas =
-                recorder.DEPRECATED_beginRecording(pre->width(), pre->height(), NULL, 0);
+                recorder.DEPRECATED_beginRecording(pre->cullRect().width(), 
+                                                   pre->cullRect().height(), 
+                                                   NULL, 0);
 
             pre->draw(recordCanvas);
 
@@ -372,15 +374,15 @@
             }
 
             canvas->save();
-                canvas->translate(SkIntToScalar(xPos), SkIntToScalar(yPos));
+                canvas->translate(xPos, yPos);
                 post->draw(canvas);
-                xPos += post->width();
+                xPos += post->cullRect().width();
             canvas->restore();
 
             if (xPos >= kWidth) {
                 // start a new line
                 xPos = 0;
-                yPos += post->height();
+                yPos += post->cullRect().height();
             }
 
             // TODO: we could also render the pre and post pictures to bitmaps
diff --git a/gm/pictureshader.cpp b/gm/pictureshader.cpp
index 0b0a99e..152cdf3 100644
--- a/gm/pictureshader.cpp
+++ b/gm/pictureshader.cpp
@@ -30,14 +30,12 @@
 
         // Build the picture.
         SkPictureRecorder recorder;
-        SkCanvas* pictureCanvas = recorder.beginRecording(SkScalarRoundToInt(tileSize),
-                                                          SkScalarRoundToInt(tileSize),
-                                                          NULL, 0);
+        SkCanvas* pictureCanvas = recorder.beginRecording(tileSize, tileSize, NULL, 0);
         this->drawTile(pictureCanvas);
         fPicture.reset(recorder.endRecording());
 
         // Build a reference bitmap.
-        fBitmap.allocN32Pixels(SkScalarRoundToInt(tileSize), SkScalarRoundToInt(tileSize));
+        fBitmap.allocN32Pixels(SkScalarCeilToInt(tileSize), SkScalarCeilToInt(tileSize));
         fBitmap.eraseColor(SK_ColorTRANSPARENT);
         SkCanvas bitmapCanvas(fBitmap);
         this->drawTile(&bitmapCanvas);
diff --git a/gm/pictureshadertile.cpp b/gm/pictureshadertile.cpp
index 9343da3..ecea553 100644
--- a/gm/pictureshadertile.cpp
+++ b/gm/pictureshadertile.cpp
@@ -61,9 +61,7 @@
 public:
     PictureShaderTileGM() {
         SkPictureRecorder recorder;
-        SkCanvas* pictureCanvas = recorder.beginRecording(SkScalarCeilToInt(kPictureSize),
-                                                          SkScalarCeilToInt(kPictureSize),
-                                                          NULL, 0);
+        SkCanvas* pictureCanvas = recorder.beginRecording(kPictureSize, kPictureSize, NULL, 0);
         drawScene(pictureCanvas, kPictureSize);
         SkAutoTUnref<SkPicture> picture(recorder.endRecording());
 
diff --git a/gyp/skia_for_android_framework_defines.gypi b/gyp/skia_for_android_framework_defines.gypi
index 7a42d97..e343680 100644
--- a/gyp/skia_for_android_framework_defines.gypi
+++ b/gyp/skia_for_android_framework_defines.gypi
@@ -19,6 +19,7 @@
       # Transitional, for deprecated SkCanvas::SaveFlags methods.
       'SK_ATTR_DEPRECATED=SK_NOTHING_ARG1',
       'SK_SUPPORT_LEGACY_DEFAULT_PICTURE_CTOR',
+      'SK_LEGACY_PICTURE_SIZE_API',
     ],
   },
 }
diff --git a/gyp/skia_for_chromium_defines.gypi b/gyp/skia_for_chromium_defines.gypi
index 7d21666..ac4a19f 100644
--- a/gyp/skia_for_chromium_defines.gypi
+++ b/gyp/skia_for_chromium_defines.gypi
@@ -19,6 +19,7 @@
       'SK_IGNORE_ETC1_SUPPORT',
       'SK_IGNORE_GPU_DITHER',
       'SK_SUPPORT_LEGACY_IMAGECACHE_NAME',
+      'SK_LEGACY_PICTURE_SIZE_API',
     ],
   },
 }
diff --git a/include/core/SkPicture.h b/include/core/SkPicture.h
index 30d0821..6a54040 100644
--- a/include/core/SkPicture.h
+++ b/include/core/SkPicture.h
@@ -120,19 +120,16 @@
     */
     void draw(SkCanvas* canvas, SkDrawPictureCallback* = NULL) const;
 
-    /** Return the width of the picture's recording canvas. This
-        value reflects what was passed to setSize(), and does not necessarily
-        reflect the bounds of what has been recorded into the picture.
-        @return the width of the picture's recording canvas
-    */
-    int width() const { return fWidth; }
+#ifdef SK_LEGACY_PICTURE_SIZE_API
+    int width() const  { return SkScalarCeilToInt(fCullWidth); }
+    int height() const { return SkScalarCeilToInt(fCullHeight); }
+#endif
 
-    /** Return the height of the picture's recording canvas. This
-        value reflects what was passed to setSize(), and does not necessarily
-        reflect the bounds of what has been recorded into the picture.
-        @return the height of the picture's recording canvas
+    /** Return the cull rect used when creating this picture: { 0, 0, cullWidth, cullHeight }.
+        It does not necessarily reflect the bounds of what has been recorded into the picture.
+        @return the cull rect used to create this picture
     */
-    int height() const { return fHeight; }
+    const SkRect cullRect() const { return SkRect::MakeWH(fCullWidth, fCullHeight); }
 
     /** Return a non-zero, unique value representing the picture. This call is
         only valid when not recording. Between a beginRecording/endRecording
@@ -180,7 +177,7 @@
         If false is returned, SkPictInfo is unmodified.
     */
     static bool InternalOnly_StreamIsSKP(SkStream*, SkPictInfo*);
-    static bool InternalOnly_BufferIsSKP(SkReadBuffer&, SkPictInfo*);
+    static bool InternalOnly_BufferIsSKP(SkReadBuffer*, SkPictInfo*);
 
     /** Return true if the picture is suitable for rendering on the GPU.
      */
@@ -244,19 +241,21 @@
     // V32: Removed SkPaintOptionsAndroid from SkPaint
     // V33: Serialize only public API of effects.
     // V34: Add SkTextBlob serialization.
+    // V35: Store SkRect (rather then width & height) in header
 
     // Note: If the picture version needs to be increased then please follow the
     // steps to generate new SKPs in (only accessible to Googlers): http://goo.gl/qATVcw
 
     // Only SKPs within the min/current picture version range (inclusive) can be read.
     static const uint32_t MIN_PICTURE_VERSION = 19;
-    static const uint32_t CURRENT_PICTURE_VERSION = 34;
+    static const uint32_t CURRENT_PICTURE_VERSION = 35;
 
     mutable uint32_t      fUniqueID;
 
     // TODO: make SkPictureData const when clone method goes away
     SkAutoTDelete<SkPictureData> fData;
-    int                   fWidth, fHeight;
+    const SkScalar                        fCullWidth;
+    const SkScalar                        fCullHeight;
     mutable SkAutoTUnref<const AccelData> fAccelData;
 
     mutable SkTDArray<DeletionListener*> fDeletionListeners;  // pointers are refed
@@ -266,9 +265,9 @@
 
     // Create a new SkPicture from an existing SkPictureData. The new picture
     // takes ownership of 'data'.
-    SkPicture(SkPictureData* data, int width, int height);
+    SkPicture(SkPictureData* data, SkScalar width, SkScalar height);
 
-    SkPicture(int width, int height, const SkPictureRecord& record, bool deepCopyOps);
+    SkPicture(SkScalar width, SkScalar height, const SkPictureRecord& record, bool deepCopyOps);
 
     // An OperationList encapsulates a set of operation offsets into the picture byte
     // stream along with the CTMs needed for those operation.
@@ -303,7 +302,7 @@
     typedef SkRefCnt INHERITED;
 
     // Takes ownership of the SkRecord, refs the (optional) BBH.
-    SkPicture(int width, int height, SkRecord*, SkBBoxHierarchy*);
+    SkPicture(SkScalar width, SkScalar height, SkRecord*, SkBBoxHierarchy*);
     // Return as a new SkPicture that's backed by SkRecord.
     static SkPicture* Forwardport(const SkPicture&);
 
diff --git a/include/core/SkPictureRecorder.h b/include/core/SkPictureRecorder.h
index bd86148..a3f7d48 100644
--- a/include/core/SkPictureRecorder.h
+++ b/include/core/SkPictureRecorder.h
@@ -28,16 +28,23 @@
     SkPictureRecorder();
     ~SkPictureRecorder();
 
+#ifdef SK_LEGACY_PICTURE_SIZE_API
+    SkCanvas* beginRecording(int width, int height,
+                             SkBBHFactory* bbhFactory = NULL,
+                             uint32_t recordFlags = 0) {
+        return this->beginRecording(SkIntToScalar(width), SkIntToScalar(height),
+                                    bbhFactory, recordFlags);
+    }
+#endif
+
     /** Returns the canvas that records the drawing commands.
-        @param width the base width for the picture, as if the recording
-                     canvas' bitmap had this width.
-        @param height the base width for the picture, as if the recording
-                     canvas' bitmap had this height.
+        @param width the width of the cull rect used when recording this picture.
+        @param height the height of the cull rect used when recording this picture.
         @param bbhFactory factory to create desired acceleration structure
         @param recordFlags optional flags that control recording.
         @return the canvas.
     */
-    SkCanvas* beginRecording(int width, int height,
+    SkCanvas* beginRecording(SkScalar width, SkScalar height,
                              SkBBHFactory* bbhFactory = NULL,
                              uint32_t recordFlags = 0);
 
@@ -47,12 +54,12 @@
     // then we use EXPERIMENTAL_beginRecording().
 
     // Old slower backend.
-    SkCanvas* DEPRECATED_beginRecording(int width, int height,
+    SkCanvas* DEPRECATED_beginRecording(SkScalar width, SkScalar height,
                                         SkBBHFactory* bbhFactory = NULL,
                                         uint32_t recordFlags = 0);
 
     // New faster backend.
-    SkCanvas* EXPERIMENTAL_beginRecording(int width, int height,
+    SkCanvas* EXPERIMENTAL_beginRecording(SkScalar width, SkScalar height,
                                           SkBBHFactory* bbhFactory = NULL);
 
     /** Returns the recording canvas if one is active, or NULL if recording is
@@ -87,9 +94,8 @@
     friend class SkPictureRecorderReplayTester; // for unit testing
     void partialReplay(SkCanvas* canvas) const;
 
-    int fWidth;
-    int fHeight;
-
+    SkScalar                      fCullWidth;
+    SkScalar                      fCullHeight;
     SkAutoTUnref<SkBBoxHierarchy> fBBH;
 
     // One of these two canvases will be non-NULL.
diff --git a/samplecode/SampleFilterFuzz.cpp b/samplecode/SampleFilterFuzz.cpp
index 298219d..8aa48ed 100644
--- a/samplecode/SampleFilterFuzz.cpp
+++ b/samplecode/SampleFilterFuzz.cpp
@@ -371,7 +371,9 @@
     {
         SkRTreeFactory factory;
         SkPictureRecorder recorder;
-        SkCanvas* recordingCanvas = recorder.beginRecording(kBitmapSize, kBitmapSize, &factory, 0);
+        SkCanvas* recordingCanvas = recorder.beginRecording(SkIntToScalar(kBitmapSize), 
+                                                            SkIntToScalar(kBitmapSize), 
+                                                            &factory, 0);
         drawSomething(recordingCanvas);
         SkAutoTUnref<SkPicture> pict(recorder.endRecording());
         filter = SkPictureImageFilter::Create(pict.get(), make_rect());
diff --git a/samplecode/SamplePictFile.cpp b/samplecode/SamplePictFile.cpp
index 87a0e67..3d7acfc 100644
--- a/samplecode/SamplePictFile.cpp
+++ b/samplecode/SamplePictFile.cpp
@@ -123,7 +123,9 @@
         if (SkImageDecoder::DecodeFile(path, &bm)) {
             bm.setImmutable();
             SkPictureRecorder recorder;
-            SkCanvas* can = recorder.beginRecording(bm.width(), bm.height(), NULL, 0);
+            SkCanvas* can = recorder.beginRecording(SkIntToScalar(bm.width()), 
+                                                    SkIntToScalar(bm.height()), 
+                                                    NULL, 0);
             can->drawBitmap(bm, 0, 0, NULL);
             pic.reset(recorder.endRecording());
         } else {
@@ -135,13 +137,16 @@
             }
 
             if (false) {
-                SkSurface* surf = SkSurface::NewRasterPMColor(pic->width(), pic->height());
+                SkSurface* surf = SkSurface::NewRasterPMColor(SkScalarCeilToInt(pic->cullRect().width()), 
+                                                              SkScalarCeilToInt(pic->cullRect().height()));
                 surf->getCanvas()->drawPicture(pic);
                 surf->unref();
             }
             if (false) { // re-record
                 SkPictureRecorder recorder;
-                pic->draw(recorder.beginRecording(pic->width(), pic->height(), NULL, 0));
+                pic->draw(recorder.beginRecording(pic->cullRect().width(), 
+                                                  pic->cullRect().height(), 
+                                                  NULL, 0));
                 SkAutoTUnref<SkPicture> p2(recorder.endRecording());
 
                 SkString path2(path);
@@ -177,7 +182,9 @@
         }
 
         SkPictureRecorder recorder;
-        pic->draw(recorder.beginRecording(pic->width(), pic->height(), factory.get(), 0));
+        pic->draw(recorder.beginRecording(pic->cullRect().width(), 
+                                          pic->cullRect().height(), 
+                                          factory.get(), 0));
         return recorder.endRecording();
     }
 
diff --git a/src/core/SkBBoxRecord.cpp b/src/core/SkBBoxRecord.cpp
index 5837a88..5fe42f9 100644
--- a/src/core/SkBBoxRecord.cpp
+++ b/src/core/SkBBoxRecord.cpp
@@ -313,8 +313,7 @@
 
 void SkBBoxRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
                                  const SkPaint* paint) {
-    SkRect bounds = SkRect::MakeWH(SkIntToScalar(picture->width()),
-                                   SkIntToScalar(picture->height()));
+    SkRect bounds = picture->cullRect();
     // todo: wonder if we should allow passing an optional matrix to transformBounds so we don't
     // end up transforming the rect twice.
     if (matrix) {
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 16459b0..2b08a94 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -2445,7 +2445,7 @@
         }
     }
 
-    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->width(), picture->height());
+    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
 
     picture->draw(this);
 }
@@ -2549,16 +2549,16 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 SkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
-                                                 const SkPaint* paint, int width, int height)
+                                                 const SkPaint* paint, const SkRect& bounds)
     : fCanvas(canvas)
     , fSaveCount(canvas->getSaveCount())
 {
     if (NULL != paint) {
-        SkRect bounds = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
+        SkRect newBounds = bounds;
         if (matrix) {
-            matrix->mapRect(&bounds);
+            matrix->mapRect(&newBounds);
         }
-        canvas->saveLayer(&bounds, paint);
+        canvas->saveLayer(&newBounds, paint);
     } else if (NULL != matrix) {
         canvas->save();
     }
diff --git a/src/core/SkCanvasPriv.h b/src/core/SkCanvasPriv.h
index 9f66baa..dfae154 100644
--- a/src/core/SkCanvasPriv.h
+++ b/src/core/SkCanvasPriv.h
@@ -12,7 +12,7 @@
 
 class SkAutoCanvasMatrixPaint : SkNoncopyable {
 public:
-    SkAutoCanvasMatrixPaint(SkCanvas*, const SkMatrix*, const SkPaint*, int width, int height);
+    SkAutoCanvasMatrixPaint(SkCanvas*, const SkMatrix*, const SkPaint*, const SkRect& bounds);
     ~SkAutoCanvasMatrixPaint();
 
 private:
diff --git a/src/core/SkPicture.cpp b/src/core/SkPicture.cpp
index e958f96..92551d3 100644
--- a/src/core/SkPicture.cpp
+++ b/src/core/SkPicture.cpp
@@ -262,11 +262,11 @@
 #endif
 
 // fRecord OK
-SkPicture::SkPicture(int width, int height,
+SkPicture::SkPicture(SkScalar width, SkScalar height,
                      const SkPictureRecord& record,
                      bool deepCopyOps)
-    : fWidth(width)
-    , fHeight(height)
+    : fCullWidth(width)
+    , fCullHeight(height)
     , fAnalysis() {
     this->needsNewGenID();
 
@@ -277,10 +277,11 @@
 
 // Create an SkPictureData-backed SkPicture from an SkRecord.
 // This for compatibility with serialization code only.  This is not cheap.
-static SkPicture* backport(const SkRecord& src, int width, int height) {
+static SkPicture* backport(const SkRecord& src, const SkRect& cullRect) {
     SkPictureRecorder recorder;
     SkRecordDraw(src,
-                 recorder.DEPRECATED_beginRecording(width, height), NULL/*bbh*/, NULL/*callback*/);
+                 recorder.DEPRECATED_beginRecording(cullRect.width(), cullRect.height()), 
+                 NULL/*bbh*/, NULL/*callback*/);
     return recorder.endRecording();
 }
 
@@ -351,7 +352,7 @@
     // If the query contains the whole picture, don't bother with the BBH.
     SkRect clipBounds = { 0, 0, 0, 0 };
     (void)canvas->getClipBounds(&clipBounds);
-    const bool useBBH = !clipBounds.contains(SkRect::MakeWH(this->width(), this->height()));
+    const bool useBBH = !clipBounds.contains(this->cullRect());
 
     if (NULL != fData.get()) {
         SkPicturePlayback playback(this);
@@ -392,7 +393,32 @@
     // Check magic bytes.
     SkPictInfo info;
     SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
-    if (!stream->read(&info, sizeof(info)) || !IsValidPictInfo(info)) {
+
+    if (!stream->read(&info.fMagic, sizeof(kMagic))) {
+        return false;
+    }
+
+    info.fVersion = stream->readU32();
+
+#ifndef V35_COMPATIBILITY_CODE
+    if (info.fVersion < 35) {
+        info.fCullRect.fLeft = 0;
+        info.fCullRect.fTop = 0;
+        info.fCullRect.fRight = SkIntToScalar(stream->readU32());
+        info.fCullRect.fBottom = SkIntToScalar(stream->readU32());
+    } else {
+#endif
+        info.fCullRect.fLeft = stream->readScalar();
+        info.fCullRect.fTop = stream->readScalar();
+        info.fCullRect.fRight = stream->readScalar();
+        info.fCullRect.fBottom = stream->readScalar();
+#ifndef V35_COMPATIBILITY_CODE
+    }
+#endif
+
+    info.fFlags = stream->readU32();
+
+    if (!IsValidPictInfo(info)) {
         return false;
     }
 
@@ -403,11 +429,33 @@
 }
 
 // fRecord OK
-bool SkPicture::InternalOnly_BufferIsSKP(SkReadBuffer& buffer, SkPictInfo* pInfo) {
+bool SkPicture::InternalOnly_BufferIsSKP(SkReadBuffer* buffer, SkPictInfo* pInfo) {
     // Check magic bytes.
     SkPictInfo info;
     SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
-    if (!buffer.readByteArray(&info, sizeof(info)) || !IsValidPictInfo(info)) {
+
+    if (!buffer->readByteArray(&info.fMagic, sizeof(kMagic))) {
+        return false;
+    }
+
+    info.fVersion = buffer->readUInt();
+
+#ifndef V35_COMPATIBILITY_CODE
+    if (info.fVersion < 35) {
+        info.fCullRect.fLeft = 0;
+        info.fCullRect.fTop = 0;
+        info.fCullRect.fRight = SkIntToScalar(buffer->readUInt());
+        info.fCullRect.fBottom = SkIntToScalar(buffer->readUInt());
+    } else {
+#endif
+        buffer->readRect(&info.fCullRect);
+#ifndef V35_COMPATIBILITY_CODE
+    }
+#endif
+
+    info.fFlags = buffer->readUInt();
+
+    if (!IsValidPictInfo(info)) {
         return false;
     }
 
@@ -418,19 +466,20 @@
 }
 
 // fRecord OK
-SkPicture::SkPicture(SkPictureData* data, int width, int height)
+SkPicture::SkPicture(SkPictureData* data, SkScalar width, SkScalar height)
     : fData(data)
-    , fWidth(width)
-    , fHeight(height)
+    , fCullWidth(width)
+    , fCullHeight(height)
     , fAnalysis() {
     this->needsNewGenID();
 }
 
 SkPicture* SkPicture::Forwardport(const SkPicture& src) {
     SkAutoTDelete<SkRecord> record(SkNEW(SkRecord));
-    SkRecorder canvas(record.get(), src.width(), src.height());
+    SkRecorder canvas(record.get(), src.cullRect().width(), src.cullRect().height());
     src.draw(&canvas);
-    return SkNEW_ARGS(SkPicture, (src.width(), src.height(), record.detach(), NULL/*bbh*/));
+    return SkNEW_ARGS(SkPicture, (src.cullRect().width(), src.cullRect().height(), 
+                                  record.detach(), NULL/*bbh*/));
 }
 
 // fRecord OK
@@ -447,7 +496,7 @@
         if (NULL == data) {
             return NULL;
         }
-        const SkPicture src(data, info.fWidth, info.fHeight);
+        const SkPicture src(data, info.fCullRect.width(), info.fCullRect.height());
         return Forwardport(src);
     }
 
@@ -458,7 +507,7 @@
 SkPicture* SkPicture::CreateFromBuffer(SkReadBuffer& buffer) {
     SkPictInfo info;
 
-    if (!InternalOnly_BufferIsSKP(buffer, &info)) {
+    if (!InternalOnly_BufferIsSKP(&buffer, &info)) {
         return NULL;
     }
 
@@ -468,7 +517,7 @@
         if (NULL == data) {
             return NULL;
         }
-        const SkPicture src(data, info.fWidth, info.fHeight);
+        const SkPicture src(data, info.fCullRect.width(), info.fCullRect.height());
         return Forwardport(src);
     }
 
@@ -484,8 +533,7 @@
 
     // Set picture info after magic bytes in the header
     info->fVersion = CURRENT_PICTURE_VERSION;
-    info->fWidth = fWidth;
-    info->fHeight = fHeight;
+    info->fCullRect = this->cullRect();
     info->fFlags = SkPictInfo::kCrossProcess_Flag;
     // TODO: remove this flag, since we're always float (now)
     info->fFlags |= SkPictInfo::kScalarIsFloat_Flag;
@@ -502,13 +550,14 @@
     // If we're a new-format picture, backport to old format for serialization.
     SkAutoTDelete<SkPicture> oldFormat;
     if (NULL == data && NULL != fRecord.get()) {
-        oldFormat.reset(backport(*fRecord, fWidth, fHeight));
+        oldFormat.reset(backport(*fRecord, this->cullRect()));
         data = oldFormat->fData.get();
         SkASSERT(NULL != data);
     }
 
     SkPictInfo info;
     this->createHeader(&info);
+    SkASSERT(sizeof(SkPictInfo) == 32);
     stream->write(&info, sizeof(info));
 
     if (NULL != data) {
@@ -526,14 +575,17 @@
     // If we're a new-format picture, backport to old format for serialization.
     SkAutoTDelete<SkPicture> oldFormat;
     if (NULL == data && NULL != fRecord.get()) {
-        oldFormat.reset(backport(*fRecord, fWidth, fHeight));
+        oldFormat.reset(backport(*fRecord, this->cullRect()));
         data = oldFormat->fData.get();
         SkASSERT(NULL != data);
     }
 
     SkPictInfo info;
     this->createHeader(&info);
-    buffer.writeByteArray(&info, sizeof(info));
+    buffer.writeByteArray(&info.fMagic, sizeof(info.fMagic));
+    buffer.writeUInt(info.fVersion);
+    buffer.writeRect(info.fCullRect);
+    buffer.writeUInt(info.fFlags);
 
     if (NULL != data) {
         buffer.writeBool(true);
@@ -605,9 +657,9 @@
 }
 
 // fRecord OK
-SkPicture::SkPicture(int width, int height, SkRecord* record, SkBBoxHierarchy* bbh)
-    : fWidth(width)
-    , fHeight(height)
+SkPicture::SkPicture(SkScalar width, SkScalar height, SkRecord* record, SkBBoxHierarchy* bbh)
+    : fCullWidth(width)
+    , fCullHeight(height)
     , fRecord(record)
     , fBBH(SkSafeRef(bbh))
     , fAnalysis(*record) {
diff --git a/src/core/SkPictureData.h b/src/core/SkPictureData.h
index a5f1ae0..019bfb2 100644
--- a/src/core/SkPictureData.h
+++ b/src/core/SkPictureData.h
@@ -37,8 +37,7 @@
 
     char        fMagic[8];
     uint32_t    fVersion;
-    uint32_t    fWidth;
-    uint32_t    fHeight;
+    SkRect      fCullRect;
     uint32_t    fFlags;
 };
 
diff --git a/src/core/SkPictureRecorder.cpp b/src/core/SkPictureRecorder.cpp
index d90f885..fadb937 100644
--- a/src/core/SkPictureRecorder.cpp
+++ b/src/core/SkPictureRecorder.cpp
@@ -17,7 +17,7 @@
 
 SkPictureRecorder::~SkPictureRecorder() {}
 
-SkCanvas* SkPictureRecorder::beginRecording(int width, int height,
+SkCanvas* SkPictureRecorder::beginRecording(SkScalar width, SkScalar height,
                                             SkBBHFactory* bbhFactory /* = NULL */,
                                             uint32_t recordFlags /* = 0 */) {
 #ifdef SK_PICTURE_USE_SK_RECORD
@@ -27,11 +27,11 @@
 #endif
 }
 
-SkCanvas* SkPictureRecorder::DEPRECATED_beginRecording(int width, int height,
+SkCanvas* SkPictureRecorder::DEPRECATED_beginRecording(SkScalar width, SkScalar height,
                                                        SkBBHFactory* bbhFactory /* = NULL */,
                                                        uint32_t recordFlags /* = 0 */) {
-    fWidth = width;
-    fHeight = height;
+    fCullWidth = width;
+    fCullHeight = height;
 
     const SkISize size = SkISize::Make(width, height);
 
@@ -49,10 +49,10 @@
     return this->getRecordingCanvas();
 }
 
-SkCanvas* SkPictureRecorder::EXPERIMENTAL_beginRecording(int width, int height,
+SkCanvas* SkPictureRecorder::EXPERIMENTAL_beginRecording(SkScalar width, SkScalar height,
                                                          SkBBHFactory* bbhFactory /* = NULL */) {
-    fWidth = width;
-    fHeight = height;
+    fCullWidth = width;
+    fCullHeight = height;
 
     if (NULL != bbhFactory) {
         fBBH.reset((*bbhFactory)(width, height));
@@ -75,13 +75,15 @@
     SkPicture* picture = NULL;
 
     if (NULL != fRecord.get()) {
-        picture = SkNEW_ARGS(SkPicture, (fWidth, fHeight, fRecord.detach(), fBBH.get()));
+        picture = SkNEW_ARGS(SkPicture, (fCullWidth, fCullHeight, 
+                                         fRecord.detach(), fBBH.get()));
     }
 
     if (NULL != fPictureRecord.get()) {
         fPictureRecord->endRecording();
         const bool deepCopyOps = false;
-        picture = SkNEW_ARGS(SkPicture, (fWidth, fHeight, *fPictureRecord.get(), deepCopyOps));
+        picture = SkNEW_ARGS(SkPicture, (fCullWidth, fCullHeight, 
+                                         *fPictureRecord.get(), deepCopyOps));
     }
 
     return picture;
@@ -104,7 +106,8 @@
 
     if (NULL != fPictureRecord.get()) {
         const bool deepCopyOps = true;
-        SkPicture picture(fWidth, fHeight, *fPictureRecord.get(), deepCopyOps);
+        SkPicture picture(fCullWidth, fCullHeight, 
+                          *fPictureRecord.get(), deepCopyOps);
         picture.draw(canvas);
     }
 }
diff --git a/src/core/SkPictureShader.cpp b/src/core/SkPictureShader.cpp
index 3e0eb65..73ab170 100644
--- a/src/core/SkPictureShader.cpp
+++ b/src/core/SkPictureShader.cpp
@@ -22,10 +22,9 @@
                                  const SkMatrix* localMatrix, const SkRect* tile)
     : INHERITED(localMatrix)
     , fPicture(SkRef(picture))
+    , fTile(NULL != tile ? *tile : picture->cullRect())
     , fTmx(tmx)
     , fTmy(tmy) {
-    fTile = tile ? *tile : SkRect::MakeWH(SkIntToScalar(picture->width()),
-                                          SkIntToScalar(picture->height()));
 }
 
 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
@@ -43,8 +42,7 @@
 
 SkPictureShader* SkPictureShader::Create(const SkPicture* picture, TileMode tmx, TileMode tmy,
                                          const SkMatrix* localMatrix, const SkRect* tile) {
-    if (!picture || 0 == picture->width() || 0 == picture->height()
-        || (NULL != tile && tile->isEmpty())) {
+    if (!picture || picture->cullRect().isEmpty() || (NULL != tile && tile->isEmpty())) {
         return NULL;
     }
     return SkNEW_ARGS(SkPictureShader, (picture, tmx, tmy, localMatrix, tile));
@@ -70,7 +68,7 @@
 }
 
 SkShader* SkPictureShader::refBitmapShader(const SkMatrix& matrix, const SkMatrix* localM) const {
-    SkASSERT(fPicture && fPicture->width() > 0 && fPicture->height() > 0);
+    SkASSERT(fPicture && !fPicture->cullRect().isEmpty());
 
     SkMatrix m;
     m.setConcat(matrix, this->getLocalMatrix());
@@ -201,9 +199,11 @@
         "clamp", "repeat", "mirror"
     };
 
-    str->appendf("PictureShader: [%d:%d] ",
-                 fPicture ? fPicture->width() : 0,
-                 fPicture ? fPicture->height() : 0);
+    str->appendf("PictureShader: [%f:%f:%f:%f] ",
+                 fPicture ? fPicture->cullRect().fLeft : 0,
+                 fPicture ? fPicture->cullRect().fTop : 0,
+                 fPicture ? fPicture->cullRect().fRight : 0,
+                 fPicture ? fPicture->cullRect().fBottom : 0);
 
     str->appendf("(%s, %s)", gTileModeName[fTmx], gTileModeName[fTmy]);
 
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp
index 7985e2b..0117ade 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -321,7 +321,7 @@
     }
 
     Bounds bounds(const DrawPicture& op) const {
-        SkRect dst = SkRect::MakeWH(op.picture->width(), op.picture->height());
+        SkRect dst = op.picture->cullRect();
         if (op.matrix) {
             op.matrix->mapRect(&dst);
         }
diff --git a/src/effects/SkPictureImageFilter.cpp b/src/effects/SkPictureImageFilter.cpp
index c28175a..3ca0c09 100644
--- a/src/effects/SkPictureImageFilter.cpp
+++ b/src/effects/SkPictureImageFilter.cpp
@@ -13,19 +13,16 @@
 #include "SkValidationUtils.h"
 
 SkPictureImageFilter::SkPictureImageFilter(const SkPicture* picture, uint32_t uniqueID)
-  : INHERITED(0, 0, NULL, uniqueID),
-    fPicture(picture),
-    fCropRect(SkRect::MakeWH(picture ? SkIntToScalar(picture->width()) : 0,
-                             picture ? SkIntToScalar(picture->height()) : 0)) {
-    SkSafeRef(fPicture);
+    : INHERITED(0, 0, NULL, uniqueID)
+    , fPicture(SkSafeRef(picture))
+    , fCropRect(NULL != picture ? picture->cullRect() : SkRect::MakeEmpty()) {
 }
 
 SkPictureImageFilter::SkPictureImageFilter(const SkPicture* picture, const SkRect& cropRect,
                                            uint32_t uniqueID)
-  : INHERITED(0, 0, NULL, uniqueID),
-    fPicture(picture),
-    fCropRect(cropRect) {
-    SkSafeRef(fPicture);
+    : INHERITED(0, 0, NULL, uniqueID)
+    , fPicture(SkSafeRef(picture))
+    , fCropRect(cropRect) {
 }
 
 SkPictureImageFilter::~SkPictureImageFilter() {
diff --git a/src/gpu/GrPictureUtils.cpp b/src/gpu/GrPictureUtils.cpp
index 521160a..4b0f77f 100644
--- a/src/gpu/GrPictureUtils.cpp
+++ b/src/gpu/GrPictureUtils.cpp
@@ -23,10 +23,11 @@
     CollectLayers(const SkPicture* pict, GrAccelData* accelData)
         : fPictureID(pict->uniqueID())
         , fCTM(&SkMatrix::I())
-        , fCurrentClipBounds(SkIRect::MakeXYWH(0, 0, pict->width(), pict->height()))
         , fSaveLayersInStack(0)
         , fAccelData(accelData) {
 
+        pict->cullRect().roundOut(&fCurrentClipBounds);
+
         if (NULL == pict->fRecord.get()) {
             return;
         }
@@ -255,7 +256,7 @@
 // GPUOptimize is only intended to be called within the context of SkGpuDevice's
 // EXPERIMENTAL_optimize method.
 const GrAccelData* GPUOptimize(const SkPicture* pict) {
-    if (NULL == pict || 0 == pict->width() || 0 == pict->height()) {
+    if (NULL == pict || pict->cullRect().isEmpty()) {
         return NULL;
     }
 
diff --git a/src/utils/SkDumpCanvas.cpp b/src/utils/SkDumpCanvas.cpp
index 5e3d153..e7b64a4 100644
--- a/src/utils/SkDumpCanvas.cpp
+++ b/src/utils/SkDumpCanvas.cpp
@@ -434,13 +434,15 @@
 
 void SkDumpCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
                                  const SkPaint* paint) {
-    this->dump(kDrawPicture_Verb, NULL, "drawPicture(%p) %d:%d", picture,
-               picture->width(), picture->height());
+    this->dump(kDrawPicture_Verb, NULL, "drawPicture(%p) %f:%f:%f:%f", picture,
+               picture->cullRect().fLeft, picture->cullRect().fTop,
+               picture->cullRect().fRight, picture->cullRect().fBottom);
     fNestLevel += 1;
     this->INHERITED::onDrawPicture(picture, matrix, paint);
     fNestLevel -= 1;
-    this->dump(kDrawPicture_Verb, NULL, "endPicture(%p) %d:%d", &picture,
-               picture->width(), picture->height());
+    this->dump(kDrawPicture_Verb, NULL, "endPicture(%p) %f:%f:%f:%f", &picture,
+               picture->cullRect().fLeft, picture->cullRect().fTop,
+               picture->cullRect().fRight, picture->cullRect().fBottom);
 }
 
 void SkDumpCanvas::drawVertices(VertexMode vmode, int vertexCount,
diff --git a/src/utils/SkGatherPixelRefsAndRects.cpp b/src/utils/SkGatherPixelRefsAndRects.cpp
index f46fe8e..ee5b147 100644
--- a/src/utils/SkGatherPixelRefsAndRects.cpp
+++ b/src/utils/SkGatherPixelRefsAndRects.cpp
@@ -11,15 +11,15 @@
 
 void SkPictureUtils::GatherPixelRefsAndRects(SkPicture* pict,
                                              SkPictureUtils::SkPixelRefContainer* prCont) {
-    if (0 == pict->width() || 0 == pict->height()) {
+    if (pict->cullRect().isEmpty()) {
         return ;
     }
 
-    SkGatherPixelRefsAndRectsDevice device(pict->width(), pict->height(), prCont);
+    SkGatherPixelRefsAndRectsDevice device(SkScalarCeilToInt(pict->cullRect().width()), 
+                                           SkScalarCeilToInt(pict->cullRect().height()), 
+                                           prCont);
     SkNoSaveLayerCanvas canvas(&device);
 
-    canvas.clipRect(SkRect::MakeWH(SkIntToScalar(pict->width()),
-                                   SkIntToScalar(pict->height())),
-                    SkRegion::kIntersect_Op, false);
+    canvas.clipRect(pict->cullRect(), SkRegion::kIntersect_Op, false);
     canvas.drawPicture(pict);
 }
diff --git a/src/utils/SkPictureUtils.cpp b/src/utils/SkPictureUtils.cpp
index 85d523f..4f4d2bf 100644
--- a/src/utils/SkPictureUtils.cpp
+++ b/src/utils/SkPictureUtils.cpp
@@ -196,16 +196,16 @@
     }
 
     // this test also handles if either area or pict's width/height are empty
-    if (!SkRect::Intersects(area,
-                            SkRect::MakeWH(SkIntToScalar(pict->width()),
-                                           SkIntToScalar(pict->height())))) {
+    if (!SkRect::Intersects(area, pict->cullRect())) {
         return NULL;
     }
 
     SkTDArray<SkPixelRef*> array;
     PixelRefSet prset(&array);
 
-    GatherPixelRefDevice device(pict->width(), pict->height(), &prset);
+    GatherPixelRefDevice device(SkScalarCeilToInt(pict->cullRect().width()), 
+                                SkScalarCeilToInt(pict->cullRect().height()), 
+                                &prset);
     SkNoSaveLayerCanvas canvas(&device);
 
     canvas.clipRect(area, SkRegion::kIntersect_Op, false);
diff --git a/src/utils/debugger/SkDebugCanvas.cpp b/src/utils/debugger/SkDebugCanvas.cpp
index 2b0eab7..85fb7a4 100644
--- a/src/utils/debugger/SkDebugCanvas.cpp
+++ b/src/utils/debugger/SkDebugCanvas.cpp
@@ -14,11 +14,10 @@
 #include "SkDevice.h"
 #include "SkXfermode.h"
 
-SkDebugCanvas::SkDebugCanvas(int width, int height)
-        : INHERITED(width, height)
+SkDebugCanvas::SkDebugCanvas(int windowWidth, int windowHeight)
+        : INHERITED(windowWidth, windowHeight)
         , fPicture(NULL)
-        , fWidth(width)
-        , fHeight(height)
+        , fWindowSize(SkISize::Make(windowWidth, windowHeight))
         , fFilter(false)
         , fMegaVizMode(false)
         , fIndex(0)
@@ -76,7 +75,7 @@
 
     SkCanvas canvas(bitmap);
     canvas.translate(SkIntToScalar(-x), SkIntToScalar(-y));
-    applyUserTransform(&canvas);
+    this->applyUserTransform(&canvas);
 
     int layer = 0;
     SkColor prev = bitmap.getColor(0,0);
@@ -255,10 +254,10 @@
         }
         canvas->clear(SK_ColorTRANSPARENT);
         canvas->resetMatrix();
-        SkRect rect = SkRect::MakeWH(SkIntToScalar(fWidth),
-                                     SkIntToScalar(fHeight));
-        canvas->clipRect(rect, SkRegion::kReplace_Op );
-        applyUserTransform(canvas);
+        SkRect rect = SkRect::MakeWH(SkIntToScalar(fWindowSize.fWidth), 
+                                     SkIntToScalar(fWindowSize.fHeight));
+        canvas->clipRect(rect, SkRegion::kReplace_Op);
+        this->applyUserTransform(canvas);
         fOutstandingSaveCount = 0;
     }
 
@@ -292,17 +291,7 @@
 
     for (; i <= index; i++) {
         if (i == index && fFilter) {
-            SkPaint p;
-            p.setColor(0xAAFFFFFF);
-            canvas->save();
-            canvas->resetMatrix();
-            SkRect mask;
-            mask.set(SkIntToScalar(0), SkIntToScalar(0),
-                    SkIntToScalar(fWidth), SkIntToScalar(fHeight));
-            canvas->clipRect(mask, SkRegion::kReplace_Op, false);
-            canvas->drawRectCoords(SkIntToScalar(0), SkIntToScalar(0),
-                    SkIntToScalar(fWidth), SkIntToScalar(fHeight), p);
-            canvas->restore();
+            canvas->clear(0xAAFFFFFF);
         }
 
         if (fCommandVector[i]->isVisible()) {
@@ -321,12 +310,13 @@
     }
 
     if (fMegaVizMode) {
-        SkRect r = SkRect::MakeWH(SkIntToScalar(fWidth), SkIntToScalar(fHeight));
+        SkRect r = SkRect::MakeWH(SkIntToScalar(fWindowSize.fWidth), 
+                                  SkIntToScalar(fWindowSize.fHeight));
         r.outset(SK_Scalar1, SK_Scalar1);
 
         canvas->save();
         // nuke the CTM
-        canvas->setMatrix(SkMatrix::I());
+        canvas->resetMatrix();
         // turn off clipping
         canvas->clipRect(r, SkRegion::kReplace_Op);
 
diff --git a/src/utils/debugger/SkDebugCanvas.h b/src/utils/debugger/SkDebugCanvas.h
index 94ad426..2e9a032 100644
--- a/src/utils/debugger/SkDebugCanvas.h
+++ b/src/utils/debugger/SkDebugCanvas.h
@@ -145,10 +145,7 @@
      */
     void toggleCommand(int index, bool toggle);
 
-    void setBounds(int width, int height) {
-        fWidth = width;
-        fHeight = height;
-    }
+    void setWindowSize(int width, int height) { fWindowSize.set(width, height); }
 
     void setUserMatrix(SkMatrix matrix) {
         fUserMatrix = matrix;
@@ -259,8 +256,7 @@
 private:
     SkTDArray<SkDrawCommand*> fCommandVector;
     SkPicture* fPicture;
-    int fWidth;
-    int fHeight;
+    SkISize fWindowSize;
     bool fFilter;
     bool fMegaVizMode;
     int fIndex;
diff --git a/src/utils/debugger/SkDrawCommand.cpp b/src/utils/debugger/SkDrawCommand.cpp
index 3b1a028..3a07396 100644
--- a/src/utils/debugger/SkDrawCommand.cpp
+++ b/src/utils/debugger/SkDrawCommand.cpp
@@ -523,7 +523,9 @@
     }
 
     SkString* temp = new SkString;
-    temp->appendf("SkPicture: W: %d H: %d", picture->width(), picture->height());
+    temp->appendf("SkPicture: L: %f T: %f R: %f B: %f",
+                  picture->cullRect().fLeft, picture->cullRect().fTop,
+                  picture->cullRect().fRight, picture->cullRect().fBottom);
     fInfo.push(temp);
     if (NULL != matrix) {
         fInfo.push(SkObjectParser::MatrixToString(*matrix));
@@ -541,9 +543,7 @@
     canvas->clear(0xFFFFFFFF);
     canvas->save();
 
-    SkRect bounds = SkRect::MakeWH(SkIntToScalar(fPicture->width()),
-                                   SkIntToScalar(fPicture->height()));
-    xlate_and_scale_to_bounds(canvas, bounds);
+    xlate_and_scale_to_bounds(canvas, fPicture->cullRect());
 
     canvas->drawPicture(fPicture.get());
 
diff --git a/tests/CanvasTest.cpp b/tests/CanvasTest.cpp
index 5d6a8d8..d460051 100644
--- a/tests/CanvasTest.cpp
+++ b/tests/CanvasTest.cpp
@@ -463,7 +463,8 @@
                                 skiatest::Reporter*,
                                 CanvasTestStep*) {
     SkPictureRecorder recorder;
-    SkCanvas* testCanvas = recorder.beginRecording(kWidth, kHeight, NULL, 0);
+    SkCanvas* testCanvas = recorder.beginRecording(SkIntToScalar(kWidth), SkIntToScalar(kHeight), 
+                                                   NULL, 0);
     testCanvas->scale(SkIntToScalar(2), SkIntToScalar(1));
     testCanvas->clipRect(kTestRect);
     testCanvas->drawRect(kTestRect, kTestPaint);
@@ -688,12 +689,16 @@
         testStep->setAssertMessageFormat(kPictureDrawAssertMessageFormat);
         SkPictureRecorder referenceRecorder;
         SkCanvas* referenceCanvas =
-            referenceRecorder.DEPRECATED_beginRecording(kWidth, kHeight, NULL, recordFlags);
+            referenceRecorder.DEPRECATED_beginRecording(SkIntToScalar(kWidth), 
+                                                        SkIntToScalar(kHeight), 
+                                                        NULL, recordFlags);
         testStep->draw(referenceCanvas, reporter);
 
         SkPictureRecorder testRecorder;
         SkCanvas* testCanvas =
-            testRecorder.DEPRECATED_beginRecording(kWidth, kHeight, NULL, recordFlags);
+            testRecorder.DEPRECATED_beginRecording(SkIntToScalar(kWidth), 
+                                                   SkIntToScalar(kHeight), 
+                                                   NULL, recordFlags);
         testStep->draw(testCanvas, reporter);
         testStep->setAssertMessageFormat(kPictureSecondDrawAssertMessageFormat);
         testStep->draw(testCanvas, reporter);
diff --git a/tests/ImageFilterTest.cpp b/tests/ImageFilterTest.cpp
index 778cc3f..a8cd5d0 100644
--- a/tests/ImageFilterTest.cpp
+++ b/tests/ImageFilterTest.cpp
@@ -421,7 +421,8 @@
     }
 }
 
-static void drawSaveLayerPicture(int width, int height, int tileSize, SkBBHFactory* factory, SkBitmap* result) {
+static void draw_saveLayer_picture(int width, int height, int tileSize, 
+                                   SkBBHFactory* factory, SkBitmap* result) {
 
     SkMatrix matrix;
     matrix.setTranslate(SkIntToScalar(50), 0);
@@ -434,7 +435,9 @@
     paint.setImageFilter(imageFilter.get());
     SkPictureRecorder recorder;
     SkRect bounds = SkRect::Make(SkIRect::MakeXYWH(0, 0, 50, 50));
-    SkCanvas* recordingCanvas = recorder.beginRecording(width, height, factory, 0);
+    SkCanvas* recordingCanvas = recorder.beginRecording(SkIntToScalar(width), 
+                                                        SkIntToScalar(height), 
+                                                        factory, 0);
     recordingCanvas->translate(-55, 0);
     recordingCanvas->saveLayer(&bounds, &paint);
     recordingCanvas->restore();
@@ -457,8 +460,8 @@
     SkBitmap result1, result2;
     SkRTreeFactory factory;
 
-    drawSaveLayerPicture(width, height, tileSize, &factory, &result1);
-    drawSaveLayerPicture(width, height, tileSize, NULL, &result2);
+    draw_saveLayer_picture(width, height, tileSize, &factory, &result1);
+    draw_saveLayer_picture(width, height, tileSize, NULL, &result2);
 
     for (int y = 0; y < height; y++) {
         int diffs = memcmp(result1.getAddr32(0, y), result2.getAddr32(0, y), result1.rowBytes());
@@ -513,7 +516,7 @@
     REPORTER_ASSERT(reporter, bounds == expectedBounds);
 }
 
-static void drawBlurredRect(SkCanvas* canvas) {
+static void draw_blurred_rect(SkCanvas* canvas) {
     SkAutoTUnref<SkImageFilter> filter(SkBlurImageFilter::Create(SkIntToScalar(8), 0));
     SkPaint filterPaint;
     filterPaint.setColor(SK_ColorWHITE);
@@ -525,7 +528,7 @@
     canvas->restore();
 }
 
-static void drawPictureClipped(SkCanvas* canvas, const SkRect& clipRect, const SkPicture* picture) {
+static void draw_picture_clipped(SkCanvas* canvas, const SkRect& clipRect, const SkPicture* picture) {
     canvas->save();
     canvas->clipRect(clipRect);
     canvas->drawPicture(picture);
@@ -555,17 +558,21 @@
 
     SkPictureRecorder recorder1, recorder2;
     // The only difference between these two pictures is that one has RTree aceleration.
-    SkCanvas* recordingCanvas1 = recorder1.beginRecording(width, height, NULL, 0);
-    SkCanvas* recordingCanvas2 = recorder2.beginRecording(width, height, &factory, 0);
-    drawBlurredRect(recordingCanvas1);
-    drawBlurredRect(recordingCanvas2);
+    SkCanvas* recordingCanvas1 = recorder1.beginRecording(SkIntToScalar(width), 
+                                                          SkIntToScalar(height), 
+                                                          NULL, 0);
+    SkCanvas* recordingCanvas2 = recorder2.beginRecording(SkIntToScalar(width), 
+                                                          SkIntToScalar(height), 
+                                                          &factory, 0);
+    draw_blurred_rect(recordingCanvas1);
+    draw_blurred_rect(recordingCanvas2);
     SkAutoTUnref<SkPicture> picture1(recorder1.endRecording());
     SkAutoTUnref<SkPicture> picture2(recorder2.endRecording());
     for (int y = 0; y < height; y += tileSize) {
         for (int x = 0; x < width; x += tileSize) {
             SkRect tileRect = SkRect::Make(SkIRect::MakeXYWH(x, y, tileSize, tileSize));
-            drawPictureClipped(&canvas1, tileRect, picture1);
-            drawPictureClipped(&canvas2, tileRect, picture2);
+            draw_picture_clipped(&canvas1, tileRect, picture1);
+            draw_picture_clipped(&canvas2, tileRect, picture2);
         }
     }
     for (int y = 0; y < height; y++) {
diff --git a/tests/PathOpsSkpClipTest.cpp b/tests/PathOpsSkpClipTest.cpp
index a94412e..d413a08 100755
--- a/tests/PathOpsSkpClipTest.cpp
+++ b/tests/PathOpsSkpClipTest.cpp
@@ -394,22 +394,21 @@
 
 static SkMSec timePict(SkPicture* pic, SkCanvas* canvas) {
     canvas->save();
-    int pWidth = pic->width();
-    int pHeight = pic->height();
-    const int maxDimension = 1000;
+    SkScalar pWidth = pic->cullRect().width();
+    SkScalar pHeight = pic->cullRect().height();
+    const SkScalar maxDimension = 1000.0f;
     const int slices = 3;
-    int xInterval = SkTMax(pWidth - maxDimension, 0) / (slices - 1);
-    int yInterval = SkTMax(pHeight - maxDimension, 0) / (slices - 1);
-    SkRect rect = {0, 0, SkIntToScalar(SkTMin(maxDimension, pWidth)),
-            SkIntToScalar(SkTMin(maxDimension, pHeight))};
+    SkScalar xInterval = SkTMax(pWidth - maxDimension, 0.0f) / (slices - 1);
+    SkScalar yInterval = SkTMax(pHeight - maxDimension, 0.0f) / (slices - 1);
+    SkRect rect = {0, 0, SkTMin(maxDimension, pWidth), SkTMin(maxDimension, pHeight) };
     canvas->clipRect(rect);
     SkMSec start = SkTime::GetMSecs();
     for (int x = 0; x < slices; ++x) {
         for (int y = 0; y < slices; ++y) {
             pic->draw(canvas);
-            canvas->translate(0, SkIntToScalar(yInterval));
+            canvas->translate(0, yInterval);
         }
-        canvas->translate(SkIntToScalar(xInterval), SkIntToScalar(-yInterval * slices));
+        canvas->translate(xInterval, -yInterval * slices);
     }
     SkMSec end = SkTime::GetMSecs();
     canvas->restore();
@@ -473,16 +472,16 @@
             SkDebugf("unable to decode %s\n", fFilename);
             goto finish;
         }
-        int width = pic->width();
-        int height = pic->height();
+        SkScalar width = pic->cullRect().width();
+        SkScalar height = pic->cullRect().height();
         SkBitmap oldBitmap, opBitmap;
         fScale = 1;
         while (width / fScale > 32767 || height / fScale > 32767) {
             ++fScale;
         }
         do {
-            int dimX = (width + fScale - 1) / fScale;
-            int dimY = (height + fScale - 1) / fScale;
+            int dimX = SkScalarCeilToInt(width / fScale);
+            int dimY = SkScalarCeilToInt(height / fScale);
             if (oldBitmap.allocN32Pixels(dimX, dimY) &&
                 opBitmap.allocN32Pixels(dimX, dimY)) {
                 break;
@@ -490,7 +489,7 @@
             SkDebugf("-%d-", fScale);
         } while (++fScale < 256);
         if (fScale >= 256) {
-            SkDebugf("unable to allocate bitmap for %s (w=%d h=%d)\n", fFilename,
+            SkDebugf("unable to allocate bitmap for %s (w=%f h=%f)\n", fFilename,
                     width, height);
             goto finish;
         }
diff --git a/tests/PictureTest.cpp b/tests/PictureTest.cpp
index 627e96e..8b19df2 100644
--- a/tests/PictureTest.cpp
+++ b/tests/PictureTest.cpp
@@ -882,7 +882,7 @@
         {
             SkPictureRecorder recorder;
 
-            SkCanvas* c = recorder.beginRecording(kWidth, kHeight);
+            SkCanvas* c = recorder.beginRecording(SkIntToScalar(kWidth), SkIntToScalar(kHeight));
 
             c->saveLayer(NULL, NULL);
             c->restore();
@@ -914,7 +914,8 @@
         {
             SkPictureRecorder recorder;
 
-            SkCanvas* c = recorder.beginRecording(kWidth, kHeight);
+            SkCanvas* c = recorder.beginRecording(SkIntToScalar(kWidth), 
+                                                  SkIntToScalar(kHeight));
             // 1)
             c->saveLayer(NULL, NULL); // layer #0
             c->restore();
@@ -1187,7 +1188,8 @@
 void check_save_state(skiatest::Reporter* reporter, SkPicture* picture,
                       unsigned int numSaves, unsigned int numSaveLayers,
                       unsigned int numRestores) {
-    SaveCountingCanvas canvas(picture->width(), picture->height());
+    SaveCountingCanvas canvas(SkScalarCeilToInt(picture->cullRect().width()), 
+                              SkScalarCeilToInt(picture->cullRect().height()));
 
     picture->draw(&canvas);
 
@@ -1443,7 +1445,8 @@
 
 static SkData* serialized_picture_from_bitmap(const SkBitmap& bitmap) {
     SkPictureRecorder recorder;
-    SkCanvas* canvas = recorder.beginRecording(bitmap.width(), bitmap.height());
+    SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(bitmap.width()), 
+                                               SkIntToScalar(bitmap.height()));
     canvas->drawBitmap(bitmap, 0, 0);
     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
 
diff --git a/tests/SerializationTest.cpp b/tests/SerializationTest.cpp
index 2dc0c62..4e11f12 100644
--- a/tests/SerializationTest.cpp
+++ b/tests/SerializationTest.cpp
@@ -263,7 +263,8 @@
 
 static SkBitmap draw_picture(SkPicture& picture) {
      SkBitmap bitmap;
-     bitmap.allocN32Pixels(picture.width(), picture.height());
+     bitmap.allocN32Pixels(SkScalarCeilToInt(picture.cullRect().width()), 
+                           SkScalarCeilToInt(picture.cullRect().height()));
      SkCanvas canvas(bitmap);
      picture.draw(&canvas);
      return bitmap;
@@ -315,7 +316,9 @@
     // Paint some text.
     SkPictureRecorder recorder;
     SkIRect canvasRect = SkIRect::MakeWH(kBitmapSize, kBitmapSize);
-    SkCanvas* canvas = recorder.beginRecording(canvasRect.width(), canvasRect.height(), NULL, 0);
+    SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(canvasRect.width()), 
+                                               SkIntToScalar(canvasRect.height()), 
+                                               NULL, 0);
     canvas->drawColor(SK_ColorWHITE);
     canvas->drawText("A", 1, 24, 32, paint);
     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
@@ -364,7 +367,7 @@
     return success;
 }
 
-static bool drawSomething(SkCanvas* canvas) {
+static bool draw_something(SkCanvas* canvas) {
     SkPaint paint;
     SkBitmap bitmap;
     bool success = make_checkerboard_bitmap(bitmap);
@@ -478,7 +481,9 @@
     // Test simple SkPicture serialization
     {
         SkPictureRecorder recorder;
-        bool didDraw = drawSomething(recorder.beginRecording(kBitmapSize, kBitmapSize, NULL, 0));
+        bool didDraw = draw_something(recorder.beginRecording(SkIntToScalar(kBitmapSize), 
+                                                              SkIntToScalar(kBitmapSize), 
+                                                              NULL, 0));
         REPORTER_ASSERT(reporter, didDraw);
         SkAutoTUnref<SkPicture> pict(recorder.endRecording());
 
diff --git a/tools/PictureRenderer.cpp b/tools/PictureRenderer.cpp
index 72c72a5..ed5bdfe 100644
--- a/tools/PictureRenderer.cpp
+++ b/tools/PictureRenderer.cpp
@@ -191,7 +191,7 @@
 
 int PictureRenderer::getViewWidth() {
     SkASSERT(fPicture != NULL);
-    int width = SkScalarCeilToInt(fPicture->width() * fScaleFactor);
+    int width = SkScalarCeilToInt(fPicture->cullRect().width() * fScaleFactor);
     if (fViewport.width() > 0) {
         width = SkMin32(width, fViewport.width());
     }
@@ -200,7 +200,7 @@
 
 int PictureRenderer::getViewHeight() {
     SkASSERT(fPicture != NULL);
-    int height = SkScalarCeilToInt(fPicture->height() * fScaleFactor);
+    int height = SkScalarCeilToInt(fPicture->cullRect().height() * fScaleFactor);
     if (fViewport.height() > 0) {
         height = SkMin32(height, fViewport.height());
     }
@@ -216,7 +216,8 @@
     if (kNone_BBoxHierarchyType != fBBoxHierarchyType && NULL != fPicture) {
         SkAutoTDelete<SkBBHFactory> factory(this->getFactory());
         SkPictureRecorder recorder;
-        SkCanvas* canvas = recorder.beginRecording(fPicture->width(), fPicture->height(),
+        SkCanvas* canvas = recorder.beginRecording(fPicture->cullRect().width(), 
+                                                   fPicture->cullRect().height(),
                                                    factory.get(),
                                                    this->recordFlags());
         fPicture->draw(canvas);
@@ -355,7 +356,8 @@
 bool RecordPictureRenderer::render(SkBitmap** out) {
     SkAutoTDelete<SkBBHFactory> factory(this->getFactory());
     SkPictureRecorder recorder;
-    SkCanvas* canvas = recorder.beginRecording(this->getViewWidth(), this->getViewHeight(),
+    SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(this->getViewWidth()), 
+                                               SkIntToScalar(this->getViewHeight()),
                                                factory.get(),
                                                this->recordFlags());
     this->scaleToScaleFactor(canvas);
@@ -392,7 +394,8 @@
     fCanvas->flush();
     if (NULL != out) {
         *out = SkNEW(SkBitmap);
-        setup_bitmap(*out, fPicture->width(), fPicture->height());
+        setup_bitmap(*out, SkScalarCeilToInt(fPicture->cullRect().width()), 
+                           SkScalarCeilToInt(fPicture->cullRect().height()));
         fCanvas->readPixels(*out, 0, 0);
     }
     if (fEnableWrites) {
@@ -427,7 +430,8 @@
     fCanvas->flush();
     if (NULL != out) {
         *out = SkNEW(SkBitmap);
-        setup_bitmap(*out, fPicture->width(), fPicture->height());
+        setup_bitmap(*out, SkScalarCeilToInt(fPicture->cullRect().width()), 
+                           SkScalarCeilToInt(fPicture->cullRect().height()));
         fCanvas->readPixels(*out, 0, 0);
     }
     if (fEnableWrites) {
@@ -479,10 +483,10 @@
     this->buildBBoxHierarchy();
 
     if (fTileWidthPercentage > 0) {
-        fTileWidth = sk_float_ceil2int(float(fTileWidthPercentage * fPicture->width() / 100));
+        fTileWidth = SkScalarCeilToInt(float(fTileWidthPercentage * fPicture->cullRect().width() / 100));
     }
     if (fTileHeightPercentage > 0) {
-        fTileHeight = sk_float_ceil2int(float(fTileHeightPercentage * fPicture->height() / 100));
+        fTileHeight = SkScalarCeilToInt(float(fTileHeightPercentage * fPicture->cullRect().height() / 100));
     }
 
     if (fTileMinPowerOf2Width > 0) {
@@ -647,7 +651,8 @@
     SkBitmap bitmap;
     if (out){
         *out = SkNEW(SkBitmap);
-        setup_bitmap(*out, fPicture->width(), fPicture->height());
+        setup_bitmap(*out, SkScalarCeilToInt(fPicture->cullRect().width()), 
+                           SkScalarCeilToInt(fPicture->cullRect().height()));
         setup_bitmap(&bitmap, fTileWidth, fTileHeight);
     }
     bool success = true;
@@ -712,7 +717,8 @@
 void PlaybackCreationRenderer::setup() {
     SkAutoTDelete<SkBBHFactory> factory(this->getFactory());
     fRecorder.reset(SkNEW(SkPictureRecorder));
-    SkCanvas* canvas = fRecorder->beginRecording(this->getViewWidth(), this->getViewHeight(),
+    SkCanvas* canvas = fRecorder->beginRecording(SkIntToScalar(this->getViewWidth()), 
+                                                 SkIntToScalar(this->getViewHeight()),
                                                  factory.get(),
                                                  this->recordFlags());
     this->scaleToScaleFactor(canvas);
@@ -754,8 +760,8 @@
 #endif
 
     virtual bool render(SkBitmap** out = NULL) SK_OVERRIDE {
-        SkRect bounds = SkRect::MakeWH(SkIntToScalar(fPicture->width()),
-                                       SkIntToScalar(fPicture->height()));
+        SkRect bounds = SkRect::MakeWH(SkIntToScalar(fPicture->cullRect().width()),
+                                       SkIntToScalar(fPicture->cullRect().height()));
         SkData* data = SkPictureUtils::GatherPixelRefs(fPicture, bounds);
         SkSafeUnref(data);
 
diff --git a/tools/bench_pictures_main.cpp b/tools/bench_pictures_main.cpp
index ac66dc5..4bb3194 100644
--- a/tools/bench_pictures_main.cpp
+++ b/tools/bench_pictures_main.cpp
@@ -201,13 +201,17 @@
         // Because the GPU preprocessing step relies on the in-memory picture
         // statistics we need to rerecord the picture here
         SkPictureRecorder recorder;
-        picture->draw(recorder.beginRecording(picture->width(), picture->height(), NULL, 0));
+        picture->draw(recorder.beginRecording(picture->cullRect().width(), 
+                                              picture->cullRect().height(), 
+                                              NULL, 0));
         picture.reset(recorder.endRecording());
     }
 
     SkString filename = SkOSPath::Basename(inputPath.c_str());
 
-    gWriter.bench(filename.c_str(), picture->width(), picture->height());
+    gWriter.bench(filename.c_str(), 
+                  SkScalarCeilToInt(picture->cullRect().width()), 
+                  SkScalarCeilToInt(picture->cullRect().height()));
 
     benchmark.run(picture);
 
diff --git a/tools/bench_playback.cpp b/tools/bench_playback.cpp
index f6c3ca4..f5bbc12 100644
--- a/tools/bench_playback.cpp
+++ b/tools/bench_playback.cpp
@@ -44,18 +44,23 @@
     SkTileGridFactory factory(info);
 
     SkPictureRecorder recorder;
-    src.draw(skr ? recorder.EXPERIMENTAL_beginRecording(src.width(), src.height(), &factory)
-                 : recorder.  DEPRECATED_beginRecording(src.width(), src.height(), &factory));
+    src.draw(skr ? recorder.EXPERIMENTAL_beginRecording(src.cullRect().width(), 
+                                                        src.cullRect().height(), 
+                                                        &factory)
+                 : recorder.  DEPRECATED_beginRecording(src.cullRect().width(), 
+                                                        src.cullRect().height(), 
+                                                        &factory));
     return recorder.endRecording();
 }
 
 static void bench(SkPMColor* scratch, const SkPicture& src, const char* name) {
     SkAutoTUnref<const SkPicture> picture(rerecord(src, FLAGS_skr));
 
-    SkAutoTDelete<SkCanvas> canvas(SkCanvas::NewRasterDirectN32(src.width(),
-                                                                src.height(),
-                                                                scratch,
-                                                                src.width() * sizeof(SkPMColor)));
+    SkAutoTDelete<SkCanvas> canvas(
+        SkCanvas::NewRasterDirectN32(SkScalarCeilToInt(src.cullRect().width()),
+                                     SkScalarCeilToInt(src.cullRect().height()),
+                                     scratch,
+                                     SkScalarCeilToInt(src.cullRect().width()) * sizeof(SkPMColor)));
     canvas->clipRect(SkRect::MakeWH(SkIntToScalar(FLAGS_tile), SkIntToScalar(FLAGS_tile)));
 
     // Draw once to warm any caches.  The first sample otherwise can be very noisy.
@@ -121,9 +126,13 @@
             continue;
         }
 
-        if (src->width() * src->height() > kMaxArea) {
-            SkDebugf("%s (%dx%d) is larger than hardcoded scratch bitmap (%dpx).\n",
-                     path.c_str(), src->width(), src->height(), kMaxArea);
+        if (SkScalarCeilToInt(src->cullRect().width()) * 
+            SkScalarCeilToInt(src->cullRect().height()) > kMaxArea) {
+            SkDebugf("%s (%f,%f,%f,%f) is larger than hardcoded scratch bitmap (%dpx).\n",
+                     path.c_str(), 
+                     src->cullRect().fLeft, src->cullRect().fTop,
+                     src->cullRect().fRight, src->cullRect().fBottom,
+                     kMaxArea);
             failed = true;
             continue;
         }
diff --git a/tools/bench_record.cpp b/tools/bench_record.cpp
index df1f24c..45a143f 100644
--- a/tools/bench_record.cpp
+++ b/tools/bench_record.cpp
@@ -61,9 +61,13 @@
 static void rerecord(const SkPicture& src, SkBBHFactory* bbhFactory) {
     SkPictureRecorder recorder;
     if (FLAGS_skr) {
-        src.draw(recorder.EXPERIMENTAL_beginRecording(src.width(), src.height(), bbhFactory));
+        src.draw(recorder.EXPERIMENTAL_beginRecording(src.cullRect().width(), 
+                                                      src.cullRect().height(), 
+                                                      bbhFactory));
     } else {
-        src.draw(recorder.  DEPRECATED_beginRecording(src.width(), src.height(), bbhFactory));
+        src.draw(recorder.  DEPRECATED_beginRecording(src.cullRect().width(), 
+                                                      src.cullRect().height(), 
+                                                      bbhFactory));
     }
     SkAutoTUnref<SkPicture> pic(recorder.endRecording());
 }
diff --git a/tools/dump_record.cpp b/tools/dump_record.cpp
index 4fb1cf5..bc1538f 100644
--- a/tools/dump_record.cpp
+++ b/tools/dump_record.cpp
@@ -57,7 +57,8 @@
             SkDebugf("Could not read %s as an SkPicture.\n", FLAGS_skps[i]);
             exit(1);
         }
-        const int w = src->width(), h = src->height();
+        const int w = SkScalarCeilToInt(src->cullRect().width());
+        const int h = SkScalarCeilToInt(src->cullRect().height());
 
         SkRecord record;
         SkRecorder canvas(&record, w, h);
diff --git a/tools/filtermain.cpp b/tools/filtermain.cpp
index 9df6c07..a7ed20d 100644
--- a/tools/filtermain.cpp
+++ b/tools/filtermain.cpp
@@ -677,8 +677,8 @@
 
     memset(localCount, 0, sizeof(localCount));
 
-    SkDebugCanvas debugCanvas(inPicture->width(), inPicture->height());
-    debugCanvas.setBounds(inPicture->width(), inPicture->height());
+    SkDebugCanvas debugCanvas(SkScalarCeilToInt(inPicture->cullRect().width()), 
+                              SkScalarCeilToInt(inPicture->cullRect().height()));
     inPicture->draw(&debugCanvas);
 
     // delete the initial save and restore since replaying the commands will
@@ -717,7 +717,9 @@
 
     if (!outFile.isEmpty()) {
         SkPictureRecorder recorder;
-        SkCanvas* canvas = recorder.beginRecording(inPicture->width(), inPicture->height(), NULL, 0);
+        SkCanvas* canvas = recorder.beginRecording(inPicture->cullRect().width(), 
+                                                   inPicture->cullRect().height(), 
+                                                   NULL, 0);
         debugCanvas.draw(canvas);
         SkAutoTUnref<SkPicture> outPicture(recorder.endRecording());
 
diff --git a/tools/gpuveto.cpp b/tools/gpuveto.cpp
index 68f343b..bfe3837 100644
--- a/tools/gpuveto.cpp
+++ b/tools/gpuveto.cpp
@@ -55,7 +55,9 @@
     // The SkPicture tracking information is only generated during recording
     // an isn't serialized. Replay the picture to regenerated the tracking data.
     SkPictureRecorder recorder;
-    picture->draw(recorder.beginRecording(picture->width(), picture->height(), NULL, 0));
+    picture->draw(recorder.beginRecording(picture->cullRect().width(), 
+                                          picture->cullRect().height(), 
+                                          NULL, 0));
     SkAutoTUnref<SkPicture> recorded(recorder.endRecording());
 
     if (recorded->suitableForGpuRasterization(NULL)) {
diff --git a/tools/lua/lua_pictures.cpp b/tools/lua/lua_pictures.cpp
index e19b7a3..635cf0b 100644
--- a/tools/lua/lua_pictures.cpp
+++ b/tools/lua/lua_pictures.cpp
@@ -154,7 +154,8 @@
             SkAutoTUnref<SkPicture> pic(load_picture(path));
             if (pic.get()) {
                 SkAutoTUnref<SkLuaCanvas> canvas(
-                                    new SkLuaCanvas(pic->width(), pic->height(),
+                                    new SkLuaCanvas(SkScalarCeilToInt(pic->cullRect().width()), 
+                                                    SkScalarCeilToInt(pic->cullRect().height()),
                                                     L.get(), gAccumulateFunc));
 
                 call_canvas(L.get(), canvas.get(), path, gStartCanvasFunc);
diff --git a/tools/pinspect.cpp b/tools/pinspect.cpp
index 368d6fe..18c0d70 100644
--- a/tools/pinspect.cpp
+++ b/tools/pinspect.cpp
@@ -40,7 +40,9 @@
         SkDebugf("Could not create SkPicture: %s\n", path);
         return NULL;
     }
-    printf("picture size:[%d %d]\n", pic->width(), pic->height());
+    printf("picture cullRect: [%f %f %f %f]\n", 
+           pic->cullRect().fLeft, pic->cullRect().fTop,
+           pic->cullRect().fRight, pic->cullRect().fBottom);
     return pic;
 }
 
diff --git a/tools/render_pdfs_main.cpp b/tools/render_pdfs_main.cpp
index 8e791d9..dd5f642 100644
--- a/tools/render_pdfs_main.cpp
+++ b/tools/render_pdfs_main.cpp
@@ -166,9 +166,8 @@
                           SkPicture::EncodeBitmap encoder) {
     SkAutoTUnref<SkDocument> pdfDocument(
             SkDocument::CreatePDF(output, NULL, encoder));
-    SkCanvas* canvas = pdfDocument->beginPage(
-            SkIntToScalar(picture->width()),
-            SkIntToScalar(picture->height()));
+    SkCanvas* canvas = pdfDocument->beginPage(picture->cullRect().width(), 
+                                              picture->cullRect().height());
     canvas->drawPicture(picture);
     canvas->flush();
     return pdfDocument->close();
@@ -255,8 +254,10 @@
             ++failures;
             continue;
         }
-        SkDebugf("[%-4i %6i] %-*s", picture->width(), picture->height(),
-                 maximumPathLength, basename.c_str());
+        SkDebugf("[%f,%f,%f,%f] %-*s", 
+            picture->cullRect().fLeft, picture->cullRect().fTop,
+            picture->cullRect().fRight, picture->cullRect().fBottom,
+            maximumPathLength, basename.c_str());
 
         SkAutoTDelete<SkWStream> stream(open_stream(outputDir, files[i]));
         if (!stream.get()) {
diff --git a/tools/render_pictures_main.cpp b/tools/render_pictures_main.cpp
index d508510..c9bdf13 100644
--- a/tools/render_pictures_main.cpp
+++ b/tools/render_pictures_main.cpp
@@ -184,17 +184,23 @@
         // Because the GPU preprocessing step relies on the in-memory picture
         // statistics we need to rerecord the picture here
         SkPictureRecorder recorder;
-        picture->draw(recorder.beginRecording(picture->width(), picture->height(), NULL, 0));
+        picture->draw(recorder.beginRecording(picture->cullRect().width(), 
+                                              picture->cullRect().height(), 
+                                              NULL, 0));
         picture.reset(recorder.endRecording());
     }
 
     while (FLAGS_bench_record) {
         SkPictureRecorder recorder;
-        picture->draw(recorder.beginRecording(picture->width(), picture->height(), NULL, 0));
+        picture->draw(recorder.beginRecording(picture->cullRect().width(), 
+                                              picture->cullRect().height(), 
+                                              NULL, 0));
         SkAutoTUnref<SkPicture> other(recorder.endRecording());
     }
 
-    SkDebugf("drawing... [%i %i] %s\n", picture->width(), picture->height(),
+    SkDebugf("drawing... [%f %f %f %f] %s\n", 
+             picture->cullRect().fLeft, picture->cullRect().fTop,
+             picture->cullRect().fRight, picture->cullRect().fBottom,
              inputPath.c_str());
 
     renderer.init(picture, &writePathString, &mismatchPathString, &inputFilename,
diff --git a/tools/skpinfo.cpp b/tools/skpinfo.cpp
index 1f7b465..5522965 100644
--- a/tools/skpinfo.cpp
+++ b/tools/skpinfo.cpp
@@ -12,8 +12,7 @@
 
 DEFINE_string2(input, i, "", "skp on which to report");
 DEFINE_bool2(version, v, true, "version");
-DEFINE_bool2(width, w, true, "width");
-DEFINE_bool2(height, h, true, "height");
+DEFINE_bool2(cullRect, c, true, "cullRect");
 DEFINE_bool2(flags, f, true, "flags");
 DEFINE_bool2(tags, t, true, "tags");
 DEFINE_bool2(quiet, q, false, "quiet");
@@ -59,11 +58,10 @@
     if (FLAGS_version && !FLAGS_quiet) {
         SkDebugf("Version: %d\n", info.fVersion);
     }
-    if (FLAGS_width && !FLAGS_quiet) {
-        SkDebugf("Width: %d\n", info.fWidth);
-    }
-    if (FLAGS_height && !FLAGS_quiet) {
-        SkDebugf("Height: %d\n", info.fHeight);
+    if (FLAGS_cullRect && !FLAGS_quiet) {
+        SkDebugf("Cull Rect: %f,%f,%f,%f\n", 
+                 info.fCullRect.fLeft, info.fCullRect.fTop, 
+                 info.fCullRect.fRight, info.fCullRect.fBottom);
     }
     if (FLAGS_flags && !FLAGS_quiet) {
         SkDebugf("Flags: 0x%x\n", info.fFlags);
diff --git a/tools/skpmaker.cpp b/tools/skpmaker.cpp
index 390e5ca..03f720f 100644
--- a/tools/skpmaker.cpp
+++ b/tools/skpmaker.cpp
@@ -25,18 +25,20 @@
 DEFINE_int32(width, 300, "Width of canvas to create.");
 DEFINE_string(writePath, "", "Filepath to write the SKP into.");
 
-static void skpmaker(int width, int height, int border, SkColor color,
+// Create a 'width' by 'height' skp with a 'border'-wide black border around
+// a 'color' rectangle.
+static void make_skp(SkScalar width, SkScalar height, SkScalar border, SkColor color,
                      const char *writePath) {
     SkPictureRecorder recorder;
     SkCanvas* canvas = recorder.beginRecording(width, height, NULL, 0);
     SkPaint paint;
     paint.setStyle(SkPaint::kFill_Style);
     paint.setColor(SK_ColorBLACK);
-    canvas->drawRectCoords(0, 0, SkIntToScalar(width), SkIntToScalar(height), paint);
+    SkRect r = SkRect::MakeWH(width, height);
+    canvas->drawRect(r, paint);
     paint.setColor(color);
-    canvas->drawRectCoords(SkIntToScalar(border), SkIntToScalar(border),
-                           SkIntToScalar(width - border*2), SkIntToScalar(height - border*2),
-                           paint);
+    r.inset(border, border);
+    canvas->drawRect(r, paint);
     SkAutoTUnref<SkPicture> pict(recorder.endRecording());
     SkFILEWStream stream(writePath);
     pict->serialize(&stream);
@@ -74,7 +76,10 @@
     }
 
     SkColor color = SkColorSetRGB(FLAGS_red, FLAGS_green, FLAGS_blue);
-    skpmaker(FLAGS_width, FLAGS_height, FLAGS_border, color, FLAGS_writePath[0]);
+    make_skp(SkIntToScalar(FLAGS_width), 
+             SkIntToScalar(FLAGS_height), 
+             SkIntToScalar(FLAGS_border), 
+             color, FLAGS_writePath[0]);
     return 0;
 }