Thread picture version through to SkReadBuffer.

This will let code outside SkPicture* fork its read code based on the picture version.

BUG=skia:
R=reed@google.com, robertphillips@google.com, mtklein@google.com

Author: mtklein@chromium.org

Review URL: https://codereview.chromium.org/214413008

git-svn-id: http://skia.googlecode.com/svn/trunk@13984 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/debugger/QT/SkDebuggerGUI.cpp b/debugger/QT/SkDebuggerGUI.cpp
index 58b8da7..0572550 100644
--- a/debugger/QT/SkDebuggerGUI.cpp
+++ b/debugger/QT/SkDebuggerGUI.cpp
@@ -164,15 +164,15 @@
                                                     const SkTDArray<bool>& deletedCommands) {
         // Mimics SkPicturePlayback::CreateFromStream
         SkAutoTDelete<SkTimedPicturePlayback> playback(SkNEW_ARGS(SkTimedPicturePlayback,
-                                                                  (deletedCommands)));
-        if (!playback->parseStream(stream, info, proc)) {
+                                                                  (deletedCommands, info)));
+        if (!playback->parseStream(stream, proc)) {
             return NULL; // we're invalid
         }
         return playback.detach();
     }
 
-    SkTimedPicturePlayback(const SkTDArray<bool>& deletedCommands)
-        : INHERITED()
+    SkTimedPicturePlayback(const SkTDArray<bool>& deletedCommands, const SkPictInfo& info)
+        : INHERITED(info)
         , fSkipCommands(deletedCommands)
         , fTot(0.0)
         , fCurCommand(0) {
@@ -254,14 +254,6 @@
 #endif
 
 private:
-    // SkPicturePlayback::parseStream is protected, so it can be
-    // called here, but not by our static factory function. This
-    // allows the factory function to call it.
-    bool parseStream(SkStream* stream, const SkPictInfo& info,
-                     SkPicture::InstallPixelRefProc proc) {
-        return this->INHERITED::parseStream(stream, info, proc);
-    }
-
     typedef SkPicturePlayback INHERITED;
 };
 
diff --git a/include/core/SkReadBuffer.h b/include/core/SkReadBuffer.h
index dd3301e..3befb42 100644
--- a/include/core/SkReadBuffer.h
+++ b/include/core/SkReadBuffer.h
@@ -41,6 +41,15 @@
     SkReadBuffer(SkStream* stream);
     virtual ~SkReadBuffer();
 
+    /** Return the version of the serialized picture this buffer holds, or 0 if unset. */
+    int pictureVersion() const { return fPictureVersion; }
+
+    /** This may be called at most once; most clients of SkReadBuffer should not mess with it. */
+    void setPictureVersion(int version) {
+        SkASSERT(0 == fPictureVersion);
+        fPictureVersion = version;
+    }
+
     enum Flags {
         kCrossProcess_Flag  = 1 << 0,
         kScalarIsFloat_Flag = 1 << 1,
@@ -184,6 +193,7 @@
     bool readArray(void* value, size_t size, size_t elementSize);
 
     uint32_t fFlags;
+    int fPictureVersion;
 
     void* fMemoryPtr;
 
diff --git a/src/core/SkPicture.cpp b/src/core/SkPicture.cpp
index ae0347c..5914ba4 100644
--- a/src/core/SkPicture.cpp
+++ b/src/core/SkPicture.cpp
@@ -138,8 +138,10 @@
     if (src.fPlayback) {
         fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fPlayback));
     } else if (src.fRecord) {
+        SkPictInfo info;
+        this->createHeader(&info);
         // here we do a fake src.endRecording()
-        fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fRecord));
+        fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fRecord, info));
     } else {
         fPlayback = NULL;
     }
@@ -173,6 +175,8 @@
 
 void SkPicture::clone(SkPicture* pictures, int count) const {
     SkPictCopyInfo copyInfo;
+    SkPictInfo info;
+    this->createHeader(&info);
 
     for (int i = 0; i < count; i++) {
         SkPicture* clone = &pictures[i];
@@ -190,7 +194,7 @@
             clone->fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fPlayback, &copyInfo));
         } else if (fRecord) {
             // here we do a fake src.endRecording()
-            clone->fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fRecord, true));
+            clone->fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fRecord, info, true));
         } else {
             clone->fPlayback = NULL;
         }
@@ -261,7 +265,9 @@
     if (NULL == fPlayback) {
         if (NULL != fRecord) {
             fRecord->endRecording();
-            fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fRecord));
+            SkPictInfo info;
+            this->createHeader(&info);
+            fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fRecord, info));
             SkSafeSetNull(fRecord);
         }
     }
@@ -384,7 +390,7 @@
     SkPicturePlayback* playback;
     // Check to see if there is a playback to recreate.
     if (buffer.readBool()) {
-        playback = SkPicturePlayback::CreateFromBuffer(buffer);
+        playback = SkPicturePlayback::CreateFromBuffer(buffer, info);
         if (NULL == playback) {
             return NULL;
         }
@@ -417,13 +423,13 @@
 void SkPicture::serialize(SkWStream* stream, EncodeBitmap encoder) const {
     SkPicturePlayback* playback = fPlayback;
 
+    SkPictInfo info;
+    this->createHeader(&info);
     if (NULL == playback && fRecord) {
-        playback = SkNEW_ARGS(SkPicturePlayback, (*fRecord));
+        playback = SkNEW_ARGS(SkPicturePlayback, (*fRecord, info));
     }
 
-    SkPictInfo header;
-    this->createHeader(&header);
-    stream->write(&header, sizeof(header));
+    stream->write(&info, sizeof(info));
     if (playback) {
         stream->writeBool(true);
         playback->serialize(stream, encoder);
@@ -439,13 +445,13 @@
 void SkPicture::flatten(SkWriteBuffer& buffer) const {
     SkPicturePlayback* playback = fPlayback;
 
+    SkPictInfo info;
+    this->createHeader(&info);
     if (NULL == playback && fRecord) {
-        playback = SkNEW_ARGS(SkPicturePlayback, (*fRecord));
+        playback = SkNEW_ARGS(SkPicturePlayback, (*fRecord, info));
     }
 
-    SkPictInfo header;
-    this->createHeader(&header);
-    buffer.writeByteArray(&header, sizeof(header));
+    buffer.writeByteArray(&info, sizeof(info));
     if (playback) {
         buffer.writeBool(true);
         playback->flatten(buffer);
diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp
index 8320335..f1a9473 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -24,11 +24,14 @@
  */
 #define SPEW_CLIP_SKIPPINGx
 
-SkPicturePlayback::SkPicturePlayback() {
+SkPicturePlayback::SkPicturePlayback(const SkPictInfo& info) : fInfo(info) {
     this->init();
 }
 
-SkPicturePlayback::SkPicturePlayback(const SkPictureRecord& record, bool deepCopy) {
+SkPicturePlayback::SkPicturePlayback(const SkPictureRecord& record,
+                                     const SkPictInfo& info,
+                                     bool deepCopy)
+    : fInfo(info) {
 #ifdef SK_DEBUG_SIZE
     size_t overallBytes, bitmapBytes, matricesBytes,
     paintBytes, pathBytes, pictureBytes, regionBytes;
@@ -158,7 +161,8 @@
            paint.getImageFilter();
 }
 
-SkPicturePlayback::SkPicturePlayback(const SkPicturePlayback& src, SkPictCopyInfo* deepCopyInfo) {
+SkPicturePlayback::SkPicturePlayback(const SkPicturePlayback& src, SkPictCopyInfo* deepCopyInfo)
+    : fInfo(src.fInfo) {
     this->init();
 
     fBitmapHeap.reset(SkSafeRef(src.fBitmapHeap.get()));
@@ -479,8 +483,10 @@
     return rbMask;
 }
 
-bool SkPicturePlayback::parseStreamTag(SkStream* stream, const SkPictInfo& info, uint32_t tag,
-                                       size_t size, SkPicture::InstallPixelRefProc proc) {
+bool SkPicturePlayback::parseStreamTag(SkStream* stream,
+                                       uint32_t tag,
+                                       size_t size,
+                                       SkPicture::InstallPixelRefProc proc) {
     /*
      *  By the time we encounter BUFFER_SIZE_TAG, we need to have already seen
      *  its dependents: FACTORY_TAG and TYPEFACE_TAG. These two are not required
@@ -506,7 +512,7 @@
         // Remove this code when v21 and below are no longer supported. At the
         // same time add a new 'count' variable and use it rather then reusing 'size'.
 #ifndef DISABLE_V21_COMPATIBILITY_CODE
-            if (info.fVersion >= 22) {
+            if (fInfo.fVersion >= 22) {
                 // in v22 this tag's size represents the size of the chunk in bytes
                 // and the number of factory strings is written out separately
 #endif
@@ -568,7 +574,8 @@
             }
 
             SkReadBuffer buffer(storage.get(), size);
-            buffer.setFlags(pictInfoFlagsToReadBufferFlags(info.fFlags));
+            buffer.setFlags(pictInfoFlagsToReadBufferFlags(fInfo.fFlags));
+            buffer.setPictureVersion(fInfo.fVersion);
 
             fFactoryPlayback->setupBuffer(buffer);
             fTFPlayback.setupBuffer(buffer);
@@ -654,16 +661,18 @@
 SkPicturePlayback* SkPicturePlayback::CreateFromStream(SkStream* stream,
                                                        const SkPictInfo& info,
                                                        SkPicture::InstallPixelRefProc proc) {
-    SkAutoTDelete<SkPicturePlayback> playback(SkNEW(SkPicturePlayback));
+    SkAutoTDelete<SkPicturePlayback> playback(SkNEW_ARGS(SkPicturePlayback, (info)));
 
-    if (!playback->parseStream(stream, info, proc)) {
+    if (!playback->parseStream(stream, proc)) {
         return NULL;
     }
     return playback.detach();
 }
 
-SkPicturePlayback* SkPicturePlayback::CreateFromBuffer(SkReadBuffer& buffer) {
-    SkAutoTDelete<SkPicturePlayback> playback(SkNEW(SkPicturePlayback));
+SkPicturePlayback* SkPicturePlayback::CreateFromBuffer(SkReadBuffer& buffer,
+                                                       const SkPictInfo& info) {
+    SkAutoTDelete<SkPicturePlayback> playback(SkNEW_ARGS(SkPicturePlayback, (info)));
+    buffer.setPictureVersion(info.fVersion);
 
     if (!playback->parseBuffer(buffer)) {
         return NULL;
@@ -671,7 +680,7 @@
     return playback.detach();
 }
 
-bool SkPicturePlayback::parseStream(SkStream* stream, const SkPictInfo& info,
+bool SkPicturePlayback::parseStream(SkStream* stream,
                                     SkPicture::InstallPixelRefProc proc) {
     for (;;) {
         uint32_t tag = stream->readU32();
@@ -680,7 +689,7 @@
         }
 
         uint32_t size = stream->readU32();
-        if (!this->parseStreamTag(stream, info, tag, size, proc)) {
+        if (!this->parseStreamTag(stream, tag, size, proc)) {
             return false; // we're invalid
         }
     }
diff --git a/src/core/SkPicturePlayback.h b/src/core/SkPicturePlayback.h
index 89d70a1..5fc52ae 100644
--- a/src/core/SkPicturePlayback.h
+++ b/src/core/SkPicturePlayback.h
@@ -76,12 +76,12 @@
 
 class SkPicturePlayback {
 public:
-    SkPicturePlayback();
     SkPicturePlayback(const SkPicturePlayback& src, SkPictCopyInfo* deepCopyInfo = NULL);
-    explicit SkPicturePlayback(const SkPictureRecord& record, bool deepCopy = false);
-    static SkPicturePlayback* CreateFromStream(SkStream*, const SkPictInfo&,
+    SkPicturePlayback(const SkPictureRecord& record, const SkPictInfo&, bool deepCopy = false);
+    static SkPicturePlayback* CreateFromStream(SkStream*,
+                                               const SkPictInfo&,
                                                SkPicture::InstallPixelRefProc);
-    static SkPicturePlayback* CreateFromBuffer(SkReadBuffer&);
+    static SkPicturePlayback* CreateFromBuffer(SkReadBuffer&, const SkPictInfo&);
 
     virtual ~SkPicturePlayback();
 
@@ -106,8 +106,9 @@
     void resetOpID() { fCurOffset = 0; }
 
 protected:
-    bool parseStream(SkStream*, const SkPictInfo&,
-                     SkPicture::InstallPixelRefProc);
+    explicit SkPicturePlayback(const SkPictInfo& info);
+
+    bool parseStream(SkStream*, SkPicture::InstallPixelRefProc);
     bool parseBuffer(SkReadBuffer& buffer);
 #ifdef SK_DEVELOPER
     virtual bool preDraw(int opIndex, int type);
@@ -217,8 +218,7 @@
 #endif
 
 private:    // these help us with reading/writing
-    bool parseStreamTag(SkStream*, const SkPictInfo&, uint32_t tag, size_t size,
-                        SkPicture::InstallPixelRefProc);
+    bool parseStreamTag(SkStream*, uint32_t tag, size_t size, SkPicture::InstallPixelRefProc);
     bool parseBufferTag(SkReadBuffer&, uint32_t tag, size_t size);
     void flattenToBuffer(SkWriteBuffer&) const;
 
@@ -271,6 +271,8 @@
     // The offset of the current operation when within the draw method
     size_t fCurOffset;
 
+    const SkPictInfo fInfo;
+
 #ifdef SK_BUILD_FOR_ANDROID
     SkMutex fDrawMutex;
     bool fAbortCurrentPlayback;
diff --git a/src/core/SkReadBuffer.cpp b/src/core/SkReadBuffer.cpp
index 6a590ed..b60dee3 100644
--- a/src/core/SkReadBuffer.cpp
+++ b/src/core/SkReadBuffer.cpp
@@ -25,6 +25,7 @@
 
 SkReadBuffer::SkReadBuffer() {
     fFlags = default_flags();
+    fPictureVersion = 0;
     fMemoryPtr = NULL;
 
     fBitmapStorage = NULL;
@@ -42,6 +43,7 @@
 
 SkReadBuffer::SkReadBuffer(const void* data, size_t size) {
     fFlags = default_flags();
+    fPictureVersion = 0;
     fReader.setMemory(data, size);
     fMemoryPtr = NULL;
 
@@ -60,6 +62,7 @@
 
 SkReadBuffer::SkReadBuffer(SkStream* stream) {
     fFlags = default_flags();
+    fPictureVersion = 0;
     const size_t length = stream->getLength();
     fMemoryPtr = sk_malloc_throw(length);
     stream->read(fMemoryPtr, length);