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/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;
 }