SkMultiSKP: version 2

Measurable size improvement.

BUG=skia:5370

GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2255333003

Review-Url: https://codereview.chromium.org/2255333003
diff --git a/src/utils/SkMultiPictureDocument.cpp b/src/utils/SkMultiPictureDocument.cpp
index 214e6ad..c40f1c9 100644
--- a/src/utils/SkMultiPictureDocument.cpp
+++ b/src/utils/SkMultiPictureDocument.cpp
@@ -5,33 +5,24 @@
  * found in the LICENSE file.
  */
 
-#include <vector>
-
 #include "SkMultiPictureDocument.h"
 #include "SkMultiPictureDocumentPriv.h"
 #include "SkPicture.h"
 #include "SkPictureRecorder.h"
 #include "SkStream.h"
+#include "SkTArray.h"
 
 /*
   File format:
       BEGINNING_OF_FILE:
         kMagic
-        uint32_t version_number
+        uint32_t version_number (==2)
         uint32_t page_count
         {
-          uint64_t offset
           float sizeX
           float sizeY
         } * page_count
-      FIRST_OFFSET:
         skp file
-      SECOND_OFFSET:
-        skp file
-      ...
-      LAST_OFFSET:
-        skp file
-        "\nEndOfMultiPicture\n"
 */
 
 namespace {
@@ -48,30 +39,11 @@
     return canvas;
 }
 
-struct NullWStream : public SkWStream {
-    NullWStream() : fN(0) {}
-    bool write(const void*, size_t n) override {
-        fN += n;
-        return true;
-    }
-    size_t bytesWritten() const override { return fN; }
-    size_t fN;
-};
-
-struct Page {
-  Page(SkSize s, sk_sp<SkPicture> c) : fSize(s), fContent(std::move(c)) {}
-  Page(Page&&) = default;
-  Page(const Page&) = default;
-  Page& operator=(const Page&) = default;
-  Page& operator=(Page&&) = default;
-  SkSize fSize;
-  sk_sp<SkPicture> fContent;
-};
-
 struct MultiPictureDocument final : public SkDocument {
     SkPictureRecorder fPictureRecorder;
     SkSize fCurrentPageSize;
-    std::vector<Page> fPages;
+    SkTArray<sk_sp<SkPicture>> fPages;
+    SkTArray<SkSize> fSizes;
     MultiPictureDocument(SkWStream* s, void (*d)(SkWStream*, bool))
         : SkDocument(s, d) {}
     ~MultiPictureDocument() { this->close(); }
@@ -81,35 +53,37 @@
         return trim(fPictureRecorder.beginRecording(w, h), w, h, c);
     }
     void onEndPage() override {
-        fPages.emplace_back(fCurrentPageSize,
-                            fPictureRecorder.finishRecordingAsPicture());
+        fSizes.push_back(fCurrentPageSize);
+        fPages.push_back(fPictureRecorder.finishRecordingAsPicture());
     }
     bool onClose(SkWStream* wStream) override {
         SkASSERT(wStream);
         SkASSERT(wStream->bytesWritten() == 0);
         bool good = true;
         good &= wStream->writeText(SkMultiPictureDocumentProtocol::kMagic);
-        good &= wStream->write32(SkToU32(1));  // version
-        good &= wStream->write32(SkToU32(fPages.size()));
-        uint64_t offset = wStream->bytesWritten();
-        offset += fPages.size() * sizeof(SkMultiPictureDocumentProtocol::Entry);
-        for (const auto& page : fPages) {
-            SkMultiPictureDocumentProtocol::Entry entry{
-                    offset, page.fSize.width(), page.fSize.height()};
-            good &= wStream->write(&entry, sizeof(entry));
-            NullWStream buffer;
-            page.fContent->serialize(&buffer);
-            offset += buffer.bytesWritten();
+        good &= wStream->write32(SkMultiPictureDocumentProtocol::kVersion);
+        good &= wStream->write32(SkToU32(fPages.count()));
+        for (SkSize s : fSizes) {
+            good &= wStream->write(&s, sizeof(s));
         }
-        for (const auto& page : fPages) {
-            page.fContent->serialize(wStream);
+        SkSize bigsize = SkMultiPictureDocumentProtocol::Join(fSizes);
+        SkCanvas* c = fPictureRecorder.beginRecording(SkRect::MakeSize(bigsize));
+        for (const sk_sp<SkPicture>& page : fPages) {
+            c->drawPicture(page);
+            c->drawAnnotation(SkRect::MakeEmpty(),
+                              SkMultiPictureDocumentProtocol::kEndPage,
+                              nullptr);
         }
-        SkASSERT(wStream->bytesWritten() == offset);
-        good &= wStream->writeText("\nEndOfMultiPicture\n");
-        fPages.clear();
+        sk_sp<SkPicture> p = fPictureRecorder.finishRecordingAsPicture();
+        p->serialize(wStream);
+        fPages.reset();
+        fSizes.reset();
         return good;
     }
-    void onAbort() override { fPages.clear(); }
+    void onAbort() override {
+        fPages.reset();
+        fSizes.reset();
+    }
 };
 }