work in progress

Review URL: https://codereview.chromium.org/769423002
diff --git a/experimental/tools/PageCachingDocument.cpp b/experimental/tools/PageCachingDocument.cpp
new file mode 100644
index 0000000..38e883e
--- /dev/null
+++ b/experimental/tools/PageCachingDocument.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "PageCachingDocument.h"
+#include "SkCanvas.h"
+#include "SkDocument.h"
+#include "SkPictureRecorder.h"
+#include "SkRect.h"
+#include "SkTDArray.h"
+
+namespace {
+
+typedef void (*DoneProc)(SkWStream*, bool);
+typedef SkData* (*Encoder)(size_t*, const SkBitmap&);
+
+// This class allows us to compare the relative memory consumption of
+// the PDF and SkPicture backends.
+class PageCachingDocument : public SkDocument {
+public:
+    PageCachingDocument(SkWStream*, DoneProc, Encoder, SkScalar rasterDpi);
+    virtual ~PageCachingDocument();
+    virtual SkCanvas* onBeginPage(SkScalar width,
+                                  SkScalar height,
+                                  const SkRect& content) SK_OVERRIDE;
+    virtual void onEndPage() SK_OVERRIDE;
+    virtual bool onClose(SkWStream*) SK_OVERRIDE;
+    virtual void onAbort() SK_OVERRIDE;
+
+private:
+    struct Page {
+        SkScalar fWidth;
+        SkScalar fHeight;
+        SkAutoTUnref<SkPicture> fPic;
+    };
+    SkPictureRecorder fRecorder;
+    SkTDArray<Page> fPages;
+    Encoder fEncoder;
+    SkScalar fRasterDpi;
+};
+
+PageCachingDocument::PageCachingDocument(SkWStream* stream,
+                                         DoneProc done,
+                                         Encoder encoder,
+                                         SkScalar rasterDpi)
+    : SkDocument(stream, done), fEncoder(encoder), fRasterDpi(rasterDpi) {
+}
+
+PageCachingDocument::~PageCachingDocument() {
+    for (Page* p = fPages.begin(); p != fPages.end(); ++p) {
+        p->~Page();
+    }
+}
+
+SkCanvas* PageCachingDocument::onBeginPage(SkScalar width,
+                                           SkScalar height,
+                                           const SkRect& content) {
+    Page* page = fPages.push();
+    sk_bzero(page, sizeof(*page));
+    page->fWidth = width;
+    page->fHeight = height;
+    SkASSERT(!page->fPic.get());
+    SkCanvas* canvas = fRecorder.beginRecording(content);
+    return canvas;
+}
+
+void PageCachingDocument::onEndPage() {
+    SkASSERT(fPages.count() > 0);
+    SkASSERT(!fPages[fPages.count() - 1].fPic);
+    fPages[fPages.count() - 1].fPic.reset(fRecorder.endRecording());
+}
+
+bool PageCachingDocument::onClose(SkWStream* stream) {
+    SkAutoTUnref<SkDocument> doc(
+        SkDocument::CreatePDF(stream, NULL, fEncoder, fRasterDpi));
+    for (Page* page = fPages.begin(); page != fPages.end(); ++page) {
+        SkRect cullRect = page->fPic->cullRect();
+        SkCanvas* canvas =
+            doc->beginPage(page->fWidth, page->fHeight, &cullRect);
+        canvas->drawPicture(page->fPic);
+        doc->endPage();
+    }
+    return doc->close();
+}
+
+void PageCachingDocument::onAbort() {
+}
+}  // namespace
+
+SkDocument* CreatePageCachingDocument(SkWStream* stream,
+                                      DoneProc done,
+                                      Encoder encoder,
+                                      SkScalar rasterDpi) {
+    return SkNEW_ARGS(PageCachingDocument, (stream, done, encoder, rasterDpi));
+}