No deduping dictionaries for matrices and regions.

There's little benefit to deduping matrices and regions: they're infrequently
used, and doubly infrequently reused.  Their use-weighted byte cost is tiny.

There is some downside to deduping matrices and regions.  Even when they're not
used, we prepare dictionaries for deduping them for every picture.  Each of
these dictionaries costs 160 bytes, so two unused dictionaries make a big chunk
of the ~1100 bytes it takes to allocate an SkPictureRecord. (~330 come from
parent class SkCanvas, 768 from SkPictureRecord itself, here reduced to 448).

One side benefit of not deduping these guys is that the change weighs -140 lines of code.

It may go without saying, but this breaks the picture format.

Testing: out/Debug/tests && out/Debug/dm  (which runs all picture modes by default)

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

Author: mtklein@google.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk@13149 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/core/SkPath.h b/include/core/SkPath.h
index 9b3f281..b2bb4b5 100644
--- a/include/core/SkPath.h
+++ b/include/core/SkPath.h
@@ -931,20 +931,14 @@
 
 private:
     enum SerializationOffsets {
-#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
-        kNewFormat_SerializationShift = 29, // requires 1 bit
-#endif
+        // 1 free bit at 29
         kUnused1_SerializationShift = 28,    // 1 free bit
         kDirection_SerializationShift = 26, // requires 2 bits
         kUnused2_SerializationShift = 25,    // 1 free bit
-#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
-        kOldIsOval_SerializationShift = 24,    // requires 1 bit
-#endif
+        // 1 free bit at 24
         kConvexity_SerializationShift = 16, // requires 8 bits
         kFillType_SerializationShift = 8,   // requires 8 bits
-#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
-        kOldSegmentMask_SerializationShift = 0 // requires 4 bits
-#endif
+        // 8 free bits at 0
     };
 
     SkAutoTUnref<SkPathRef> fPathRef;
@@ -1010,9 +1004,6 @@
         ed.setBounds(rect);
     }
 
-#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
-    friend class SkPathRef;     // just for SerializationOffsets
-#endif
     friend class SkAutoPathBoundsUpdate;
     friend class SkAutoDisableOvalCheck;
     friend class SkAutoDisableDirectionCheck;
diff --git a/include/core/SkPathRef.h b/include/core/SkPathRef.h
index 5358420..e10a06f 100644
--- a/include/core/SkPathRef.h
+++ b/include/core/SkPathRef.h
@@ -173,11 +173,7 @@
                                       const SkPathRef& src,
                                       const SkMatrix& matrix);
 
-    static SkPathRef* CreateFromBuffer(SkRBuffer* buffer
-#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
-        , bool newFormat, int32_t oldPacked
-#endif
-        );
+    static SkPathRef* CreateFromBuffer(SkRBuffer* buffer);
 
     /**
      * Rollsback a path ref to zero verbs and points with the assumption that the path ref will be
diff --git a/include/core/SkPicture.h b/include/core/SkPicture.h
index 4c7e4b3..d63b66b 100644
--- a/include/core/SkPicture.h
+++ b/include/core/SkPicture.h
@@ -222,10 +222,8 @@
     // V16: Move SkPath's isOval flag to SkPathRef
     // V17: SkPixelRef now writes SkImageInfo
     // V18: SkBitmap now records x,y for its pixelref origin, instead of offset.
-#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
-    static const uint32_t PRIOR_PICTURE_VERSION = 15;  // TODO: remove when .skps regenerated
-#endif
-    static const uint32_t PICTURE_VERSION = 18;
+    // V19: encode matrices and regions into the ops stream
+    static const uint32_t PICTURE_VERSION = 19;
 
     // fPlayback, fRecord, fWidth & fHeight are protected to allow derived classes to
     // install their own SkPicturePlayback-derived players,SkPictureRecord-derived
diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp
index 6692a0f..8602f4b 100644
--- a/src/core/SkPath.cpp
+++ b/src/core/SkPath.cpp
@@ -2058,11 +2058,7 @@
 
     int32_t packed = (fConvexity << kConvexity_SerializationShift) |
                      (fFillType << kFillType_SerializationShift) |
-                     (fDirection << kDirection_SerializationShift)
-#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
-                     | (0x1 << kNewFormat_SerializationShift)
-#endif
-                     ;
+                     (fDirection << kDirection_SerializationShift);
 
     buffer.write32(packed);
 
@@ -2083,15 +2079,7 @@
     fConvexity = (packed >> kConvexity_SerializationShift) & 0xFF;
     fFillType = (packed >> kFillType_SerializationShift) & 0xFF;
     fDirection = (packed >> kDirection_SerializationShift) & 0x3;
-#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
-    bool newFormat = (packed >> kNewFormat_SerializationShift) & 1;
-#endif
-
-    SkPathRef* pathRef = SkPathRef::CreateFromBuffer(&buffer
-#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
-        , newFormat, packed
-#endif
-        );
+    SkPathRef* pathRef = SkPathRef::CreateFromBuffer(&buffer);
 
     size_t sizeRead = 0;
     if (buffer.isValid()) {
diff --git a/src/core/SkPathRef.cpp b/src/core/SkPathRef.cpp
index 69afcfe..b83a451 100644
--- a/src/core/SkPathRef.cpp
+++ b/src/core/SkPathRef.cpp
@@ -105,11 +105,7 @@
     SkDEBUGCODE((*dst)->validate();)
 }
 
-SkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer
-#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
-                                   , bool newFormat, int32_t oldPacked
-#endif
-    ) {
+SkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer) {
     SkPathRef* ref = SkNEW(SkPathRef);
     bool isOval;
     uint8_t segmentMask;
@@ -121,18 +117,8 @@
     }
 
     ref->fIsFinite = (packed >> kIsFinite_SerializationShift) & 1;
-
-#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
-    if (newFormat) {
-#endif
-        segmentMask = (packed >> kSegmentMask_SerializationShift) & 0xF;
-        isOval  = (packed >> kIsOval_SerializationShift) & 1;
-#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
-    } else {
-        segmentMask = (oldPacked >> SkPath::kOldSegmentMask_SerializationShift) & 0xF;
-        isOval  = (oldPacked >> SkPath::kOldIsOval_SerializationShift) & 1;
-    }
-#endif
+    segmentMask = (packed >> kSegmentMask_SerializationShift) & 0xF;
+    isOval  = (packed >> kIsOval_SerializationShift) & 1;
 
     int32_t verbCount, pointCount, conicCount;
     if (!buffer->readU32(&(ref->fGenerationID)) ||
diff --git a/src/core/SkPicture.cpp b/src/core/SkPicture.cpp
index 15eb137..ca1b6fa 100644
--- a/src/core/SkPicture.cpp
+++ b/src/core/SkPicture.cpp
@@ -283,12 +283,7 @@
         return false;
     }
 
-    if (PICTURE_VERSION != info.fVersion
-#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
-        // V16 is backwards compatible with V15
-        && PRIOR_PICTURE_VERSION != info.fVersion  // TODO: remove when .skps regenerated
-#endif
-        ) {
+    if (PICTURE_VERSION != info.fVersion) {
         return false;
     }
 
diff --git a/src/core/SkPictureFlat.h b/src/core/SkPictureFlat.h
index 8db9609..06a9840 100644
--- a/src/core/SkPictureFlat.h
+++ b/src/core/SkPictureFlat.h
@@ -10,21 +10,16 @@
 
 //#define SK_DEBUG_SIZE
 
-#include "SkBitmap.h"
 #include "SkBitmapHeap.h"
 #include "SkChecksum.h"
 #include "SkChunkAlloc.h"
-#include "SkMatrix.h"
 #include "SkOrderedReadBuffer.h"
 #include "SkOrderedWriteBuffer.h"
 #include "SkPaint.h"
-#include "SkPath.h"
 #include "SkPicture.h"
 #include "SkPtrRecorder.h"
-#include "SkRegion.h"
 #include "SkTDynamicHash.h"
 #include "SkTRefArray.h"
-#include "SkTSearch.h"
 
 enum DrawType {
     UNUSED,
@@ -152,19 +147,17 @@
 // SkFlatData:       is a simple indexable container for the flattened data
 //                   which is agnostic to the type of data is is indexing. It is
 //                   also responsible for flattening/unflattening objects but
-//                   details of that operation are hidden in the provided procs
+//                   details of that operation are hidden in the provided traits
 // SkFlatDictionary: is an abstract templated dictionary that maintains a
 //                   searchable set of SkFlatData objects of type T.
 // SkFlatController: is an interface provided to SkFlatDictionary which handles
 //                   allocation (and unallocation in some cases). It also holds
 //                   ref count recorders and the like.
 //
-// NOTE: any class that wishes to be used in conjunction with SkFlatDictionary
-// must subclass the dictionary and provide the necessary flattening procs.
-// The end of this header contains dictionary subclasses for some common classes
-// like SkBitmap, SkMatrix, SkPaint, and SkRegion. SkFlatController must also
-// be implemented, or SkChunkFlatController can be used to use an
-// SkChunkAllocator and never do replacements.
+// NOTE: any class that wishes to be used in conjunction with SkFlatDictionary must subclass the
+// dictionary and provide the necessary flattening traits.  SkFlatController must also be
+// implemented, or SkChunkFlatController can be used to use an SkChunkAllocator and never do
+// replacements.
 //
 //
 ///////////////////////////////////////////////////////////////////////////////
@@ -574,32 +567,6 @@
                    SkFlatData::Identity, SkFlatData::Hash, SkFlatData::Equal> fHash;
 };
 
-///////////////////////////////////////////////////////////////////////////////
-// Some common dictionaries are defined here for both reference and convenience
-///////////////////////////////////////////////////////////////////////////////
-
-struct SkMatrixTraits {
-    static void flatten(SkOrderedWriteBuffer& buffer, const SkMatrix& matrix) {
-        buffer.getWriter32()->writeMatrix(matrix);
-    }
-    static void unflatten(SkOrderedReadBuffer& buffer, SkMatrix* matrix) {
-        buffer.getReader32()->readMatrix(matrix);
-    }
-};
-typedef SkFlatDictionary<SkMatrix, SkMatrixTraits> SkMatrixDictionary;
-
-
-struct SkRegionTraits {
-    static void flatten(SkOrderedWriteBuffer& buffer, const SkRegion& region) {
-        buffer.getWriter32()->writeRegion(region);
-    }
-    static void unflatten(SkOrderedReadBuffer& buffer, SkRegion* region) {
-        buffer.getReader32()->readRegion(region);
-    }
-};
-typedef SkFlatDictionary<SkRegion, SkRegionTraits> SkRegionDictionary;
-
-
 struct SkPaintTraits {
     static void flatten(SkOrderedWriteBuffer& buffer, const SkPaint& paint) {
         paint.flatten(buffer);
diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp
index 27f0c58..38f7deb 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -96,9 +96,7 @@
     record.fFlattenableHeap.setupPlaybacks();
 
     fBitmaps = record.fBitmapHeap->extractBitmaps();
-    fMatrices = record.fMatrices.unflattenToArray();
     fPaints = record.fPaints.unflattenToArray();
-    fRegions = record.fRegions.unflattenToArray();
 
     fBitmapHeap.reset(SkSafeRef(record.fBitmapHeap));
     fPathHeap.reset(SkSafeRef(record.fPathHeap));
@@ -170,8 +168,6 @@
     fBitmapHeap.reset(SkSafeRef(src.fBitmapHeap.get()));
     fPathHeap.reset(SkSafeRef(src.fPathHeap.get()));
 
-    fMatrices = SkSafeRef(src.fMatrices);
-    fRegions = SkSafeRef(src.fRegions);
     fOpData = SkSafeRef(src.fOpData);
 
     fBoundingHierarchy = src.fBoundingHierarchy;
@@ -261,10 +257,8 @@
 
 void SkPicturePlayback::init() {
     fBitmaps = NULL;
-    fMatrices = NULL;
     fPaints = NULL;
     fPictureRefs = NULL;
-    fRegions = NULL;
     fPictureCount = 0;
     fOpData = NULL;
     fFactoryPlayback = NULL;
@@ -276,9 +270,7 @@
     fOpData->unref();
 
     SkSafeUnref(fBitmaps);
-    SkSafeUnref(fMatrices);
     SkSafeUnref(fPaints);
-    SkSafeUnref(fRegions);
     SkSafeUnref(fBoundingHierarchy);
     SkSafeUnref(fStateTree);
 
@@ -291,13 +283,11 @@
 }
 
 void SkPicturePlayback::dumpSize() const {
-    SkDebugf("--- picture size: ops=%d bitmaps=%d [%d] matrices=%d [%d] paints=%d [%d] paths=%d regions=%d\n",
+    SkDebugf("--- picture size: ops=%d bitmaps=%d [%d] paints=%d [%d] paths=%d\n",
              fOpData->size(),
              SafeCount(fBitmaps), SafeCount(fBitmaps) * sizeof(SkBitmap),
-             SafeCount(fMatrices), SafeCount(fMatrices) * sizeof(SkMatrix),
              SafeCount(fPaints), SafeCount(fPaints) * sizeof(SkPaint),
-             SafeCount(fPathHeap.get()),
-             SafeCount(fRegions));
+             SafeCount(fPathHeap.get()));
 }
 
 bool SkPicturePlayback::containsBitmaps() const {
@@ -324,10 +314,8 @@
 #define PICT_BUFFER_SIZE_TAG     SkSetFourByteTag('a', 'r', 'a', 'y')
 // these are all inside the ARRAYS tag
 #define PICT_BITMAP_BUFFER_TAG  SkSetFourByteTag('b', 't', 'm', 'p')
-#define PICT_MATRIX_BUFFER_TAG  SkSetFourByteTag('m', 't', 'r', 'x')
 #define PICT_PAINT_BUFFER_TAG   SkSetFourByteTag('p', 'n', 't', ' ')
 #define PICT_PATH_BUFFER_TAG    SkSetFourByteTag('p', 't', 'h', ' ')
-#define PICT_REGION_BUFFER_TAG  SkSetFourByteTag('r', 'g', 'n', ' ')
 
 // Always write this guy last (with no length field afterwards)
 #define PICT_EOF_TAG     SkSetFourByteTag('e', 'o', 'f', ' ')
@@ -392,14 +380,6 @@
         }
     }
 
-    if ((n = SafeCount(fMatrices)) > 0) {
-        writeTagSize(buffer, PICT_MATRIX_BUFFER_TAG, n);
-        for (i = 0; i < n; i++) {
-            buffer.writeMatrix((*fMatrices)[i]);
-        }
-
-    }
-
     if ((n = SafeCount(fPaints)) > 0) {
         writeTagSize(buffer, PICT_PAINT_BUFFER_TAG, n);
         for (i = 0; i < n; i++) {
@@ -411,13 +391,6 @@
         writeTagSize(buffer, PICT_PATH_BUFFER_TAG, n);
         fPathHeap->flatten(buffer);
     }
-
-    if ((n = SafeCount(fRegions)) > 0) {
-        writeTagSize(buffer, PICT_REGION_BUFFER_TAG, n);
-        for (i = 0; i < n; i++) {
-            buffer.writeRegion((*fRegions)[i]);
-        }
-    }
 }
 
 void SkPicturePlayback::serialize(SkWStream* stream,
@@ -592,12 +565,6 @@
                 bm->setImmutable();
             }
         } break;
-        case PICT_MATRIX_BUFFER_TAG:
-            fMatrices = SkTRefArray<SkMatrix>::Create(size);
-            for (size_t i = 0; i < size; ++i) {
-                buffer.readMatrix(&fMatrices->writableAt(i));
-            }
-            break;
         case PICT_PAINT_BUFFER_TAG: {
             fPaints = SkTRefArray<SkPaint>::Create(size);
             for (size_t i = 0; i < size; ++i) {
@@ -609,12 +576,6 @@
                 fPathHeap.reset(SkNEW_ARGS(SkPathHeap, (buffer)));
             }
             break;
-        case PICT_REGION_BUFFER_TAG: {
-            fRegions = SkTRefArray<SkRegion>::Create(size);
-            for (size_t i = 0; i < size; ++i) {
-                buffer.readRegion(&fRegions->writableAt(i));
-            }
-        } break;
         default:
             // The tag was invalid.
             return false;
@@ -822,7 +783,8 @@
                 }
             } break;
             case CLIP_REGION: {
-                const SkRegion& region = getRegion(reader);
+                SkRegion region;
+                this->getRegion(reader, &region);
                 uint32_t packed = reader.readInt();
                 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
                 size_t offsetToRestore = reader.readInt();
@@ -866,9 +828,12 @@
                     reader.setOffset(offsetToRestore);
                 }
             } break;
-            case CONCAT:
-                canvas.concat(*getMatrix(reader));
+            case CONCAT: {
+                SkMatrix matrix;
+                this->getMatrix(reader, &matrix);
+                canvas.concat(matrix);
                 break;
+            }
             case DRAW_BITMAP: {
                 const SkPaint* paint = getPaint(reader);
                 const SkBitmap& bitmap = getBitmap(reader);
@@ -887,8 +852,9 @@
             case DRAW_BITMAP_MATRIX: {
                 const SkPaint* paint = getPaint(reader);
                 const SkBitmap& bitmap = getBitmap(reader);
-                const SkMatrix* matrix = getMatrix(reader);
-                canvas.drawBitmapMatrix(bitmap, *matrix, paint);
+                SkMatrix matrix;
+                this->getMatrix(reader, &matrix);
+                canvas.drawBitmapMatrix(bitmap, matrix, paint);
             } break;
             case DRAW_BITMAP_NINE: {
                 const SkPaint* paint = getPaint(reader);
@@ -1019,9 +985,9 @@
                 const SkPaint& paint = *getPaint(reader);
                 getText(reader, &text);
                 const SkPath& path = getPath(reader);
-                const SkMatrix* matrix = getMatrix(reader);
-                canvas.drawTextOnPath(text.text(), text.length(), path,
-                                      matrix, paint);
+                SkMatrix matrix;
+                this->getMatrix(reader, &matrix);
+                canvas.drawTextOnPath(text.text(), text.length(), path, &matrix, paint);
             } break;
             case DRAW_VERTICES: {
                 SkAutoTUnref<SkXfermode> xfer;
@@ -1079,7 +1045,8 @@
             } break;
             case SET_MATRIX: {
                 SkMatrix matrix;
-                matrix.setConcat(initialMatrix, *getMatrix(reader));
+                this->getMatrix(reader, &matrix);
+                matrix.postConcat(initialMatrix);
                 canvas.setMatrix(matrix);
             } break;
             case SKEW: {
@@ -1162,16 +1129,6 @@
     *size = result;
     return fPathCount;
 }
-
-int SkPicturePlayback::regions(size_t* size) {
-    size_t result = 0;
-    for (int index = 0; index < fRegionCount; index++) {
-    //    const SkRegion& region = fRegions[index];
-        result += sizeof(SkRegion); // region->size();
-    }
-    *size = result;
-    return fRegionCount;
-}
 #endif
 
 #ifdef SK_DEBUG_DUMP
@@ -1471,7 +1428,6 @@
                 DUMP_INT(offsetToRestore);
                 } break;
             case CLIP_REGION: {
-                DUMP_PTR(SkRegion, &getRegion());
                 DUMP_INT(SkRegion::Op);
                 DUMP_INT(offsetToRestore);
             } break;
@@ -1481,7 +1437,6 @@
                 DUMP_INT(offsetToRestore);
                 } break;
             case CONCAT:
-                DUMP_PTR(SkMatrix, getMatrix());
                 break;
             case DRAW_BITMAP: {
                 DUMP_PTR(SkPaint, getPaint());
@@ -1543,7 +1498,6 @@
                 DUMP_PTR(SkPaint, getPaint());
                 DUMP_TEXT();
                 DUMP_PTR(SkPath, &getPath());
-                DUMP_PTR(SkMatrix, getMatrix());
                 } break;
             case RESTORE:
                 break;
@@ -1596,21 +1550,6 @@
     if (fBitmapCount > 0)
         SkDebugf("%s0};\n", pBuffer);
 
-    if (fMatrixCount > 0)
-        SkDebugf("// matrices (%d)\n", fMatrixCount);
-    for (index = 0; index < fMatrixCount; index++) {
-        const SkMatrix& matrix = fMatrices[index];
-        dumpMatrix(matrix);
-    }
-    bufferPtr = pBuffer;
-    if (fMatrixCount > 0)
-        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
-            "Matrices matrices = {");
-    for (index = 0; index < fMatrixCount; index++)
-        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
-            "matrix%p, ", &fMatrices[index]);
-    if (fMatrixCount > 0)
-        SkDebugf("%s0};\n", pBuffer);
 
     if (fPaintCount > 0)
         SkDebugf("// paints (%d)\n", fPaintCount);
@@ -1655,20 +1594,6 @@
     if (fPictureCount > 0)
         SkDebugf("%s0};\n", pBuffer);
 
-    for (index = 0; index < fRegionCount; index++) {
-        const SkRegion& region = fRegions[index];
-        dumpRegion(region);
-    }
-    bufferPtr = pBuffer;
-    if (fRegionCount > 0)
-        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
-            "Regions regions = {");
-    for (index = 0; index < fRegionCount; index++)
-        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
-            "region%p, ", &fRegions[index]);
-    if (fRegionCount > 0)
-        SkDebugf("%s0};\n", pBuffer);
-
     const_cast<SkPicturePlayback*>(this)->dumpStream();
 }
 
diff --git a/src/core/SkPicturePlayback.h b/src/core/SkPicturePlayback.h
index 6eb9ac3..1cff0f9 100644
--- a/src/core/SkPicturePlayback.h
+++ b/src/core/SkPicturePlayback.h
@@ -109,12 +109,8 @@
         return (*fBitmaps)[index];
     }
 
-    const SkMatrix* getMatrix(SkReader32& reader) {
-        int index = reader.readInt();
-        if (index == 0) {
-            return NULL;
-        }
-        return &(*fMatrices)[index - 1];
+    void getMatrix(SkReader32& reader, SkMatrix* matrix) {
+        reader.readMatrix(matrix);
     }
 
     const SkPath& getPath(SkReader32& reader) {
@@ -151,9 +147,8 @@
         }
     }
 
-    const SkRegion& getRegion(SkReader32& reader) {
-        int index = reader.readInt();
-        return (*fRegions)[index - 1];
+    void getRegion(SkReader32& reader, SkRegion* region) {
+        reader.readRegion(region);
     }
 
     void getText(SkReader32& reader, TextContainer* text) {
@@ -169,7 +164,6 @@
     int bitmaps(size_t* size);
     int paints(size_t* size);
     int paths(size_t* size);
-    int regions(size_t* size);
 #endif
 
 #ifdef SK_DEBUG_DUMP
@@ -210,9 +204,7 @@
     SkAutoTUnref<SkPathHeap> fPathHeap;
 
     SkTRefArray<SkBitmap>* fBitmaps;
-    SkTRefArray<SkMatrix>* fMatrices;
     SkTRefArray<SkPaint>* fPaints;
-    SkTRefArray<SkRegion>* fRegions;
 
     SkData* fOpData;    // opcodes and parameters
 
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index 0851e3f..b2f9216 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -32,9 +32,7 @@
         fBoundingHierarchy(NULL),
         fStateTree(NULL),
         fFlattenableHeap(HEAP_BLOCK_SIZE),
-        fMatrices(&fFlattenableHeap),
         fPaints(&fFlattenableHeap),
-        fRegions(&fFlattenableHeap),
         fRecordFlags(flags) {
 #ifdef SK_DEBUG_SIZE
     fPointBytes = fRectBytes = fTextBytes = 0;
@@ -659,8 +657,8 @@
 
 bool SkPictureRecord::concat(const SkMatrix& matrix) {
     this->validate(fWriter.bytesWritten(), 0);
-    // op + matrix index
-    uint32_t size = 2 * kUInt32Size;
+    // op + matrix
+    uint32_t size = kUInt32Size + matrix.writeToMemory(NULL);
     size_t initialOffset = this->addDraw(CONCAT, &size);
     addMatrix(matrix);
     this->validate(initialOffset, size);
@@ -669,8 +667,8 @@
 
 void SkPictureRecord::setMatrix(const SkMatrix& matrix) {
     this->validate(fWriter.bytesWritten(), 0);
-    // op + matrix index
-    uint32_t size = 2 * kUInt32Size;
+    // op + matrix
+    uint32_t size = kUInt32Size + matrix.writeToMemory(NULL);
     size_t initialOffset = this->addDraw(SET_MATRIX, &size);
     addMatrix(matrix);
     this->validate(initialOffset, size);
@@ -823,8 +821,8 @@
 }
 
 bool SkPictureRecord::clipRegion(const SkRegion& region, SkRegion::Op op) {
-    // op + region index + clip params
-    uint32_t size = 3 * kUInt32Size;
+    // op + clip params + region
+    uint32_t size = 2 * kUInt32Size + region.writeToMemory(NULL);
     // recordRestoreOffsetPlaceholder doesn't always write an offset
     if (!fRestoreOffsetStack.isEmpty()) {
         // + restore offset
@@ -951,8 +949,8 @@
 
 void SkPictureRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
                                        const SkPaint* paint) {
-    // id + paint index + bitmap index + matrix index
-    uint32_t size = 4 * kUInt32Size;
+    // id + paint index + bitmap index + matrix
+    uint32_t size = 3 * kUInt32Size + matrix.writeToMemory(NULL);
     size_t initialOffset = this->addDraw(DRAW_BITMAP_MATRIX, &size);
     SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP_MATRIX, size) == fWriter.bytesWritten());
     addPaintPtr(paint);
@@ -1164,14 +1162,15 @@
 void SkPictureRecord::drawTextOnPath(const void* text, size_t byteLength,
                             const SkPath& path, const SkMatrix* matrix,
                             const SkPaint& paint) {
-    // op + paint index + length + 'length' worth of data + path index + matrix index
-    uint32_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * kUInt32Size;
+    // op + paint index + length + 'length' worth of data + path index + matrix
+    const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
+    uint32_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(NULL);
     size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
     SkASSERT(initialOffset+getPaintOffset(DRAW_TEXT_ON_PATH, size) == fWriter.bytesWritten());
     addPaint(paint);
     addText(text, byteLength);
     addPath(path);
-    addMatrixPtr(matrix);
+    addMatrix(m);
     this->validate(initialOffset, size);
 }
 
@@ -1294,11 +1293,7 @@
 }
 
 void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
-    addMatrixPtr(&matrix);
-}
-
-void SkPictureRecord::addMatrixPtr(const SkMatrix* matrix) {
-    this->addInt(matrix ? fMatrices.find(*matrix) : 0);
+    fWriter.writeMatrix(matrix);
 }
 
 const SkFlatData* SkPictureRecord::getFlatPaintData(const SkPaint& paint) {
@@ -1385,7 +1380,7 @@
 }
 
 void SkPictureRecord::addRegion(const SkRegion& region) {
-    addInt(fRegions.find(region));
+    fWriter.writeRegion(region);
 }
 
 void SkPictureRecord::addText(const void* text, size_t byteLength) {
diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h
index da79fc1..d098916 100644
--- a/src/core/SkPictureRecord.h
+++ b/src/core/SkPictureRecord.h
@@ -162,7 +162,6 @@
 
     void addBitmap(const SkBitmap& bitmap);
     void addMatrix(const SkMatrix& matrix);
-    void addMatrixPtr(const SkMatrix* matrix);
     const SkFlatData* addPaint(const SkPaint& paint) { return this->addPaintPtr(&paint); }
     const SkFlatData* addPaintPtr(const SkPaint* paint);
     void addFlatPaint(const SkFlatData* flatPaint);
@@ -249,9 +248,7 @@
 private:
     SkChunkFlatController fFlattenableHeap;
 
-    SkMatrixDictionary fMatrices;
     SkPaintDictionary fPaints;
-    SkRegionDictionary fRegions;
 
     SkPathHeap* fPathHeap;  // reference counted
     SkWriter32 fWriter;
diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp
index fa31743..14be6a5 100644
--- a/src/effects/SkBlurMaskFilter.cpp
+++ b/src/effects/SkBlurMaskFilter.cpp
@@ -484,10 +484,7 @@
 
 SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkFlattenableReadBuffer& buffer)
         : SkMaskFilter(buffer) {
-#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
-    // TODO: when the skps are recaptured at > v15 the SkScalarAbs can be removed
-#endif
-    fSigma = SkScalarAbs(buffer.readScalar());
+    fSigma = buffer.readScalar();
     fBlurStyle = (SkBlurMaskFilter::BlurStyle)buffer.readInt();
     fBlurFlags = buffer.readUInt() & SkBlurMaskFilter::kAll_BlurFlag;
     SkASSERT(fSigma >= 0);
diff --git a/src/effects/SkEmbossMaskFilter.cpp b/src/effects/SkEmbossMaskFilter.cpp
index 1306d6a..5c95eeb 100644
--- a/src/effects/SkEmbossMaskFilter.cpp
+++ b/src/effects/SkEmbossMaskFilter.cpp
@@ -134,10 +134,7 @@
     SkASSERT(buffer.getArrayCount() == sizeof(Light));
     buffer.readByteArray(&fLight, sizeof(Light));
     SkASSERT(fLight.fPad == 0); // for the font-cache lookup to be clean
-#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
-    // TODO: Once skps are recaptured in > v15 this SkScalarAbs can be removed
-#endif
-    fBlurSigma = SkScalarAbs(buffer.readScalar());
+    fBlurSigma = buffer.readScalar();
 }
 
 void SkEmbossMaskFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
diff --git a/tests/CanvasTest.cpp b/tests/CanvasTest.cpp
index 4ff842b..bddba59 100644
--- a/tests/CanvasTest.cpp
+++ b/tests/CanvasTest.cpp
@@ -669,14 +669,6 @@
             referenceRecord->fBitmapHeap->count() ==
             testRecord->fBitmapHeap->count(), testStep->assertMessage());
         REPORTER_ASSERT_MESSAGE(reporter,
-            referenceRecord->fMatrices.count() ==
-            testRecord->fMatrices.count(), testStep->assertMessage());
-        for (int i = 0; i < referenceRecord->fMatrices.count(); ++i) {
-            REPORTER_ASSERT_MESSAGE(reporter,
-                EQ(referenceRecord->fMatrices[i], testRecord->fMatrices[i]),
-                testStep->assertMessage());
-        }
-        REPORTER_ASSERT_MESSAGE(reporter,
             referenceRecord->fPaints.count() ==
             testRecord->fPaints.count(), testStep->assertMessage());
         for (int i = 0; i < referenceRecord->fPaints.count(); ++i) {
@@ -685,14 +677,6 @@
                                     testStep->assertMessage());
         }
         REPORTER_ASSERT_MESSAGE(reporter,
-            referenceRecord->fRegions.count() ==
-            testRecord->fRegions.count(), testStep->assertMessage());
-        for (int i = 0; i < referenceRecord->fRegions.count(); ++i) {
-            REPORTER_ASSERT_MESSAGE(reporter,
-                EQ(referenceRecord->fRegions[i], testRecord->fRegions[i]),
-                                    testStep->assertMessage());
-        }
-        REPORTER_ASSERT_MESSAGE(reporter,
             !referenceRecord->fPathHeap ==
             !testRecord->fPathHeap,
             testStep->assertMessage());