Update SkFlattenable buffers to be more modular.

This CL is an effort to stage the conversion to named
parameters for all SkFlattenable commands. This particular
stage only does the following two things...

1. Move flattenable buffers from SkFlattenable.h into
   their own header.
2. Update and Add new read write methods for better clarity
   and convenience.

BUG=

Review URL: https://codereview.appspot.com/6448095

git-svn-id: http://skia.googlecode.com/svn/trunk@4980 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkAnnotation.cpp b/src/core/SkAnnotation.cpp
index 2dc684e..62f865d 100644
--- a/src/core/SkAnnotation.cpp
+++ b/src/core/SkAnnotation.cpp
@@ -7,6 +7,7 @@
 
 #include "SkAnnotation.h"
 #include "SkDataSet.h"
+#include "SkFlattenableBuffers.h"
 #include "SkStream.h"
 
 SkAnnotation::SkAnnotation(SkDataSet* data, uint32_t flags) {
@@ -28,12 +29,12 @@
 }
 
 SkAnnotation::SkAnnotation(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
-    fFlags = buffer.readU32();
-    fDataSet = (SkDataSet*)buffer.readFlattenable();
+    fFlags = buffer.readUInt();
+    fDataSet = buffer.readFlattenableT<SkDataSet>();
 }
 
 void SkAnnotation::flatten(SkFlattenableWriteBuffer& buffer) const {
-    buffer.write32(fFlags);
+    buffer.writeUInt(fFlags);
     buffer.writeFlattenable(fDataSet);
 }
 
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp
index f135d48..70060f2 100644
--- a/src/core/SkBitmap.cpp
+++ b/src/core/SkBitmap.cpp
@@ -13,6 +13,8 @@
 #include "SkFlattenable.h"
 #include "SkMallocPixelRef.h"
 #include "SkMask.h"
+#include "SkOrderedReadBuffer.h"
+#include "SkOrderedWriteBuffer.h"
 #include "SkPixelRef.h"
 #include "SkThread.h"
 #include "SkUnPreMultiply.h"
@@ -1379,10 +1381,10 @@
     when to create a new texture.
 */
 void SkBitmap::flatten(SkFlattenableWriteBuffer& buffer) const {
-    buffer.write32(fWidth);
-    buffer.write32(fHeight);
-    buffer.write32(fRowBytes);
-    buffer.write8(fConfig);
+    buffer.writeInt(fWidth);
+    buffer.writeInt(fHeight);
+    buffer.writeInt(fRowBytes);
+    buffer.writeInt(fConfig);
     buffer.writeBool(this->isOpaque());
 
     /*  If we are called in this mode, then it is up to the caller to manage
@@ -1390,16 +1392,16 @@
     */
     if (!buffer.persistBitmapPixels()) {
         if (fPixelRef) {
-            buffer.write8(SERIALIZE_PIXELTYPE_REF_PTR);
-            buffer.write32(fPixelRefOffset);
-            buffer.writeRefCnt(fPixelRef);
+            buffer.writeInt(SERIALIZE_PIXELTYPE_REF_PTR);
+            buffer.writeUInt(fPixelRefOffset);
+            buffer.writeRefCntPtr(fPixelRef);
             return;
         } else {
             // we ignore the non-persist request, since we don't have a ref
             // ... or we could just write an empty bitmap...
             // (true) will write an empty bitmap, (false) will flatten the pix
             if (true) {
-                buffer.write8(SERIALIZE_PIXELTYPE_NONE);
+                buffer.writeInt(SERIALIZE_PIXELTYPE_NONE);
                 return;
             }
         }
@@ -1407,15 +1409,15 @@
 
     if (fPixelRef) {
         if (fPixelRef->getFactory()) {
-            buffer.write8(SERIALIZE_PIXELTYPE_REF_DATA);
-            buffer.write32(fPixelRefOffset);
+            buffer.writeInt(SERIALIZE_PIXELTYPE_REF_DATA);
+            buffer.writeUInt(fPixelRefOffset);
             buffer.writeFlattenable(fPixelRef);
             return;
         }
         // if we get here, we can't record the pixels
-        buffer.write8(SERIALIZE_PIXELTYPE_NONE);
+        buffer.writeInt(SERIALIZE_PIXELTYPE_NONE);
     } else {
-        buffer.write8(SERIALIZE_PIXELTYPE_NONE);
+        buffer.writeInt(SERIALIZE_PIXELTYPE_NONE);
     }
 }
 
@@ -1425,22 +1427,22 @@
     int width = buffer.readInt();
     int height = buffer.readInt();
     int rowBytes = buffer.readInt();
-    int config = buffer.readU8();
+    int config = buffer.readInt();
 
     this->setConfig((Config)config, width, height, rowBytes);
     this->setIsOpaque(buffer.readBool());
 
-    int reftype = buffer.readU8();
+    int reftype = buffer.readInt();
     switch (reftype) {
         case SERIALIZE_PIXELTYPE_REF_PTR: {
-            size_t offset = buffer.readU32();
-            SkPixelRef* pr = (SkPixelRef*)buffer.readRefCnt();
+            size_t offset = buffer.readUInt();
+            SkPixelRef* pr = (SkPixelRef*)buffer.readRefCntPtr();
             this->setPixelRef(pr, offset);
             break;
         }
         case SERIALIZE_PIXELTYPE_REF_DATA: {
-            size_t offset = buffer.readU32();
-            SkPixelRef* pr = static_cast<SkPixelRef*>(buffer.readFlattenable());
+            size_t offset = buffer.readUInt();
+            SkPixelRef* pr = buffer.readFlattenableT<SkPixelRef>();
             SkSafeUnref(this->setPixelRef(pr, offset));
             break;
         }
diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp
index 9b88c68..dc669cc 100644
--- a/src/core/SkBitmapProcShader.cpp
+++ b/src/core/SkBitmapProcShader.cpp
@@ -7,6 +7,7 @@
  */
 #include "SkBitmapProcShader.h"
 #include "SkColorPriv.h"
+#include "SkFlattenableBuffers.h"
 #include "SkPixelRef.h"
 
 bool SkBitmapProcShader::CanDo(const SkBitmap& bm, TileMode tx, TileMode ty) {
@@ -33,9 +34,9 @@
 
 SkBitmapProcShader::SkBitmapProcShader(SkFlattenableReadBuffer& buffer)
         : INHERITED(buffer) {
-    fRawBitmap.unflatten(buffer);
-    fState.fTileModeX = buffer.readU8();
-    fState.fTileModeY = buffer.readU8();
+    buffer.readBitmap(&fRawBitmap);
+    fState.fTileModeX = buffer.readUInt();
+    fState.fTileModeY = buffer.readUInt();
     fFlags = 0; // computed in setContext
 }
 
@@ -70,9 +71,9 @@
 void SkBitmapProcShader::flatten(SkFlattenableWriteBuffer& buffer) const {
     this->INHERITED::flatten(buffer);
 
-    fRawBitmap.flatten(buffer);
-    buffer.write8(fState.fTileModeX);
-    buffer.write8(fState.fTileModeY);
+    buffer.writeBitmap(fRawBitmap);
+    buffer.writeUInt(fState.fTileModeX);
+    buffer.writeUInt(fState.fTileModeY);
 }
 
 static bool only_scale_and_translate(const SkMatrix& matrix) {
diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp
index fda8d41..02f7160 100644
--- a/src/core/SkBlitter.cpp
+++ b/src/core/SkBlitter.cpp
@@ -12,6 +12,7 @@
 #include "SkColor.h"
 #include "SkColorFilter.h"
 #include "SkFilterShader.h"
+#include "SkFlattenableBuffers.h"
 #include "SkMask.h"
 #include "SkMaskFilter.h"
 #include "SkTemplatesPriv.h"
@@ -662,15 +663,15 @@
 
 protected:
     Sk3DShader(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
-        fProxy = static_cast<SkShader*>(buffer.readFlattenable());
-        fPMColor = buffer.readU32();
+        fProxy = buffer.readFlattenableT<SkShader>();
+        fPMColor = buffer.readColor();
         fMask = NULL;
     }
 
     virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
         this->INHERITED::flatten(buffer);
         buffer.writeFlattenable(fProxy);
-        buffer.write32(fPMColor);
+        buffer.writeColor(fPMColor);
     }
 
 private:
diff --git a/src/core/SkColorFilter.cpp b/src/core/SkColorFilter.cpp
index e781350..82a85f4 100644
--- a/src/core/SkColorFilter.cpp
+++ b/src/core/SkColorFilter.cpp
@@ -7,6 +7,7 @@
 
 #include "SkColorFilter.h"
 #include "SkFilterShader.h"
+#include "SkFlattenableBuffers.h"
 #include "SkShader.h"
 #include "SkUnPreMultiply.h"
 
@@ -48,8 +49,8 @@
 
 SkFilterShader::SkFilterShader(SkFlattenableReadBuffer& buffer) :
         INHERITED(buffer) {
-    fShader = static_cast<SkShader*>(buffer.readFlattenable());
-    fFilter = static_cast<SkColorFilter*>(buffer.readFlattenable());
+    fShader = buffer.readFlattenableT<SkShader>();
+    fFilter = buffer.readFlattenableT<SkColorFilter>();
 }
 
 SkFilterShader::~SkFilterShader() {
diff --git a/src/core/SkColorTable.cpp b/src/core/SkColorTable.cpp
index 3711de5..ce143f8 100644
--- a/src/core/SkColorTable.cpp
+++ b/src/core/SkColorTable.cpp
@@ -8,6 +8,7 @@
 
 
 #include "SkColorTable.h"
+#include "SkFlattenableBuffers.h"
 #include "SkStream.h"
 #include "SkTemplates.h"
 
@@ -142,20 +143,17 @@
     SkDEBUGCODE(fColorLockCount = 0;)
     SkDEBUGCODE(f16BitCacheLockCount = 0;)
 
-    fCount = buffer.readU16();
-    SkASSERT((unsigned)fCount <= 256);
-
-    fFlags = buffer.readU8();
-
+    fFlags = buffer.readUInt();
+    fCount = buffer.getArrayCount();
     fColors = (SkPMColor*)sk_malloc_throw(fCount * sizeof(SkPMColor));
-    buffer.read(fColors, fCount * sizeof(SkPMColor));
+    const uint32_t countRead = buffer.readColorArray(fColors);
+    SkASSERT((unsigned)fCount <= 256);
+    SkASSERT(countRead == fCount);
 }
 
 void SkColorTable::flatten(SkFlattenableWriteBuffer& buffer) const {
-    int count = this->count();
-    buffer.write16(count);
-    buffer.write8(this->getFlags());
-    buffer.writeMul4(fColors, count * sizeof(SkPMColor));
+    buffer.writeUInt(fFlags);
+    buffer.writeColorArray(fColors, fCount);
 }
 
 SK_DEFINE_FLATTENABLE_REGISTRAR(SkColorTable)
diff --git a/src/core/SkComposeShader.cpp b/src/core/SkComposeShader.cpp
index 90e4953..af3f3a5 100644
--- a/src/core/SkComposeShader.cpp
+++ b/src/core/SkComposeShader.cpp
@@ -11,6 +11,7 @@
 #include "SkColorFilter.h"
 #include "SkColorPriv.h"
 #include "SkColorShader.h"
+#include "SkFlattenableBuffers.h"
 #include "SkXfermode.h"
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -25,15 +26,15 @@
 
 SkComposeShader::SkComposeShader(SkFlattenableReadBuffer& buffer) :
     INHERITED(buffer) {
-    fShaderA = static_cast<SkShader*>(buffer.readFlattenable());
+    fShaderA = buffer.readFlattenableT<SkShader>();
     if (NULL == fShaderA) {
         fShaderA = SkNEW_ARGS(SkColorShader, (0));
     }
-    fShaderB = static_cast<SkShader*>(buffer.readFlattenable());
+    fShaderB = buffer.readFlattenableT<SkShader>();
     if (NULL == fShaderB) {
         fShaderB = SkNEW_ARGS(SkColorShader, (0));
     }
-    fMode = static_cast<SkXfermode*>(buffer.readFlattenable());
+    fMode = buffer.readFlattenableT<SkXfermode>();
 }
 
 SkComposeShader::~SkComposeShader() {
diff --git a/src/core/SkData.cpp b/src/core/SkData.cpp
index 261b571..5dbc206 100644
--- a/src/core/SkData.cpp
+++ b/src/core/SkData.cpp
@@ -6,6 +6,7 @@
  */
 
 #include "SkData.h"
+#include "SkFlattenableBuffers.h"
 
 SK_DEFINE_INST_COUNT(SkData)
 
@@ -122,25 +123,22 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 void SkData::flatten(SkFlattenableWriteBuffer& buffer) const {
-    buffer.write32(fSize);
-    buffer.writePad(fPtr, fSize);
+    buffer.writeByteArray(fPtr, fSize);
 }
 
 SkData::SkData(SkFlattenableReadBuffer& buffer) {
-    fSize = buffer.readU32();
+    fSize = buffer.getArrayCount();
     fReleaseProcContext = NULL;
 
-    if (0 == fSize) {
+    if (fSize > 0) {
+        fPtr = sk_malloc_throw(fSize);
+        fReleaseProc = sk_free_releaseproc;
+    } else {
         fPtr = NULL;
         fReleaseProc = NULL;
-    } else {
-        // buffer.read expects a 4-byte aligned size
-        size_t size4 = SkAlign4(fSize);
-        void* data = sk_malloc_throw(size4);
-        buffer.read(data, size4);
-        fPtr = data;
-        fReleaseProc = sk_free_releaseproc;
     }
+
+    buffer.readByteArray(const_cast<void*>(fPtr));
 }
 
 SK_DEFINE_FLATTENABLE_REGISTRAR(SkData)
@@ -247,11 +245,9 @@
 }
 
 void SkDataSet::flatten(SkFlattenableWriteBuffer& buffer) const {
-    buffer.write32(fCount);
+    buffer.writeInt(fCount);
     if (fCount > 0) {
-        buffer.write32(fKeySize);
-        // our first key points to all the key storage
-        buffer.writePad(fPairs[0].fKey, fKeySize);
+        buffer.writeByteArray(fPairs[0].fKey, fKeySize);
         for (int i = 0; i < fCount; ++i) {
             buffer.writeFlattenable(fPairs[i].fValue);
         }
@@ -279,19 +275,18 @@
 }
 
 SkDataSet::SkDataSet(SkFlattenableReadBuffer& buffer) {
-    fCount = buffer.readU32();
+    fCount = buffer.readInt();
     if (fCount > 0) {
-        fKeySize = buffer.readU32();
-        // we align fKeySize, since buffer.read needs to read a mul4 amount
-        fPairs = allocatePairStorage(fCount, SkAlign4(fKeySize));
+        fKeySize = buffer.getArrayCount();
+        fPairs = allocatePairStorage(fCount, fKeySize);
         char* keyStorage = (char*)(fPairs + fCount);
         
-        buffer.read(keyStorage, SkAlign4(fKeySize));
+        buffer.readByteArray(keyStorage);
         
         for (int i = 0; i < fCount; ++i) {
             fPairs[i].fKey = keyStorage;
             keyStorage += strlen(keyStorage) + 1;
-            fPairs[i].fValue = (SkData*)buffer.readFlattenable();
+            fPairs[i].fValue = buffer.readFlattenableT<SkData>();
         }
     } else {
         fKeySize = 0;
diff --git a/src/core/SkFlattenable.cpp b/src/core/SkFlattenable.cpp
index 60c04b1..0523c68 100644
--- a/src/core/SkFlattenable.cpp
+++ b/src/core/SkFlattenable.cpp
@@ -6,7 +6,6 @@
  * found in the LICENSE file.
  */
 #include "SkFlattenable.h"
-#include "SkTypeface.h"
 
 SK_DEFINE_INST_COUNT(SkFlattenable)
 
@@ -22,30 +21,6 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-SkFlattenableReadBuffer::SkFlattenableReadBuffer() {
-    fRCArray = NULL;
-    fRCCount = 0;
-
-    fTFArray = NULL;
-    fTFCount = 0;
-
-    fFactoryTDArray = NULL;
-    fFactoryArray = NULL;
-    fFactoryCount = 0;
-    
-    // Set default values. These should be explicitly set by our client
-    // via setFlags() if the buffer came from serialization.
-    fFlags = 0;
-#ifdef SK_SCALAR_IS_FLOAT
-    fFlags |= kScalarIsFloat_Flag;
-#endif
-    if (8 == sizeof(void*)) {
-        fFlags |= kPtrIs64Bit_Flag;
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
 SkNamedFactorySet::SkNamedFactorySet() : fNextAddedFactory(0) {}
 
 uint32_t SkNamedFactorySet::find(SkFlattenable::Factory factory) {
@@ -70,69 +45,6 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-SkFlattenableWriteBuffer::SkFlattenableWriteBuffer() {
-    fFlags = (Flags)0;
-    fRCSet = NULL;
-    fTFSet = NULL;
-    fFactorySet = NULL;
-    fNamedFactorySet = NULL;
-}
-
-SkFlattenableWriteBuffer::~SkFlattenableWriteBuffer() {
-    SkSafeUnref(fRCSet);
-    SkSafeUnref(fTFSet);
-    SkSafeUnref(fFactorySet);
-    SkSafeUnref(fNamedFactorySet);
-}
-
-SkRefCntSet* SkFlattenableWriteBuffer::setRefCntRecorder(SkRefCntSet* rec) {
-    SkRefCnt_SafeAssign(fRCSet, rec);
-    return rec;
-}
-
-SkRefCntSet* SkFlattenableWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) {
-    SkRefCnt_SafeAssign(fTFSet, rec);
-    return rec;
-}
-
-SkFactorySet* SkFlattenableWriteBuffer::setFactoryRecorder(SkFactorySet* rec) {
-    SkRefCnt_SafeAssign(fFactorySet, rec);
-    if (fNamedFactorySet != NULL) {
-        fNamedFactorySet->unref();
-        fNamedFactorySet = NULL;
-    }
-    return rec;
-}
-
-SkNamedFactorySet* SkFlattenableWriteBuffer::setNamedFactoryRecorder(
-        SkNamedFactorySet* rec) {
-    SkRefCnt_SafeAssign(fNamedFactorySet, rec);
-    if (fFactorySet != NULL) {
-        fFactorySet->unref();
-        fFactorySet = NULL;
-    }
-    return rec;
-}
-
-void SkFlattenableWriteBuffer::writeRefCnt(SkRefCnt* obj) {
-    SkASSERT(!isCrossProcess());
-    if (NULL == obj || NULL == fRCSet) {
-        this->write32(0);
-    } else {
-        this->write32(fRCSet->add(obj));
-    }
-}
-
-void SkFlattenableWriteBuffer::writeTypeface(SkTypeface* obj) {
-    if (NULL == obj || NULL == fTFSet) {
-        this->write32(0);
-    } else {
-        this->write32(fTFSet->add(obj));
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
 SkRefCntSet::~SkRefCntSet() {
     // call this now, while our decPtr() is sill in scope
     this->reset();
diff --git a/src/core/SkFlattenableBuffers.cpp b/src/core/SkFlattenableBuffers.cpp
new file mode 100644
index 0000000..e5a9545
--- /dev/null
+++ b/src/core/SkFlattenableBuffers.cpp
@@ -0,0 +1,68 @@
+
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "SkFlattenableBuffers.h"
+#include "SkPaint.h"
+#include "SkTypeface.h"
+
+SkFlattenableReadBuffer::SkFlattenableReadBuffer() {
+    // Set default values. These should be explicitly set by our client
+    // via setFlags() if the buffer came from serialization.
+    fFlags = 0;
+#ifdef SK_SCALAR_IS_FLOAT
+    fFlags |= kScalarIsFloat_Flag;
+#endif
+    if (8 == sizeof(void*)) {
+        fFlags |= kPtrIs64Bit_Flag;
+    }
+}
+
+SkFlattenableReadBuffer::~SkFlattenableReadBuffer() { }
+
+void* SkFlattenableReadBuffer::readFunctionPtr() {
+    void* proc;
+    SkASSERT(sizeof(void*) == this->getArrayCount());
+    this->readByteArray(&proc);
+    return proc;
+}
+
+void SkFlattenableReadBuffer::readPaint(SkPaint* paint) {
+    paint->unflatten(*this);
+}
+
+SkRefCnt* SkFlattenableReadBuffer::readRefCntPtr() {
+    void* ptrStorage[] = { NULL };
+    SkASSERT(sizeof(void*) == this->getArrayCount());
+    this->readByteArray(*ptrStorage);
+    return (SkRefCnt*)ptrStorage[0];
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkFlattenableWriteBuffer::SkFlattenableWriteBuffer() {
+    fFlags = (Flags)0;
+}
+
+SkFlattenableWriteBuffer::~SkFlattenableWriteBuffer() { }
+
+void SkFlattenableWriteBuffer::writeFunctionPtr(void* ptr) {
+    void* ptrStorage[] = { ptr };
+    this->writeByteArray(ptrStorage, sizeof(void*));
+}
+
+void SkFlattenableWriteBuffer::writePaint(const SkPaint& paint) {
+    paint.flatten(*this);
+}
+
+void SkFlattenableWriteBuffer::writeRefCntPtr(SkRefCnt* refCnt) {
+    void* ptrStorage[] = { (void*)refCnt };
+    this->writeByteArray(ptrStorage, sizeof(void*));
+}
+
+void SkFlattenableWriteBuffer::flattenObject(SkFlattenable* obj, SkFlattenableWriteBuffer& buffer) {
+    obj->flatten(buffer);
+}
diff --git a/src/core/SkGlyphCache.cpp b/src/core/SkGlyphCache.cpp
index 9ca07b9..e619419 100644
--- a/src/core/SkGlyphCache.cpp
+++ b/src/core/SkGlyphCache.cpp
@@ -10,6 +10,7 @@
 #include "SkGlyphCache.h"
 #include "SkGraphics.h"
 #include "SkPaint.h"
+#include "SkPath.h"
 #include "SkTemplates.h"
 #include "SkTLS.h"
 
diff --git a/src/core/SkMallocPixelRef.cpp b/src/core/SkMallocPixelRef.cpp
index f0bc057..758cbf2 100644
--- a/src/core/SkMallocPixelRef.cpp
+++ b/src/core/SkMallocPixelRef.cpp
@@ -7,7 +7,7 @@
  */
 #include "SkMallocPixelRef.h"
 #include "SkBitmap.h"
-#include "SkFlattenable.h"
+#include "SkFlattenableBuffers.h"
 
 SkMallocPixelRef::SkMallocPixelRef(void* storage, size_t size,
                                    SkColorTable* ctable, bool ownPixels) {
@@ -43,23 +43,20 @@
 void SkMallocPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
     this->INHERITED::flatten(buffer);
 
-    buffer.write32(fSize);
-    buffer.writePad(fStorage, fSize);
+    buffer.writeByteArray(fStorage, fSize);
+    buffer.writeBool(fCTable != NULL);
     if (fCTable) {
-        buffer.writeBool(true);
         buffer.writeFlattenable(fCTable);
-    } else {
-        buffer.writeBool(false);
     }
 }
 
 SkMallocPixelRef::SkMallocPixelRef(SkFlattenableReadBuffer& buffer)
         : INHERITED(buffer, NULL) {
-    fSize = buffer.readU32();
+    fSize = buffer.getArrayCount();
     fStorage = sk_malloc_throw(fSize);
-    buffer.read(fStorage, fSize);
+    buffer.readByteArray(fStorage);
     if (buffer.readBool()) {
-        fCTable = static_cast<SkColorTable*>(buffer.readFlattenable());
+        fCTable = buffer.readFlattenableT<SkColorTable>();
     } else {
         fCTable = NULL;
     }
diff --git a/src/core/SkOrderedReadBuffer.cpp b/src/core/SkOrderedReadBuffer.cpp
index df94907..a502c5d 100644
--- a/src/core/SkOrderedReadBuffer.cpp
+++ b/src/core/SkOrderedReadBuffer.cpp
@@ -1,20 +1,166 @@
 
 /*
- * Copyright 2011 Google Inc.
+ * Copyright 2012 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
 #include "SkOrderedReadBuffer.h"
+#include "SkStream.h"
 #include "SkTypeface.h"
 
 
 SkOrderedReadBuffer::SkOrderedReadBuffer(const void* data, size_t size) {
     fReader.setMemory(data, size);
+    fMemoryPtr = NULL;
+
+    fRCArray = NULL;
+    fRCCount = 0;
+
+    fTFArray = NULL;
+    fTFCount = 0;
+
+    fFactoryTDArray = NULL;
+    fFactoryArray = NULL;
+    fFactoryCount = 0;
+}
+
+SkOrderedReadBuffer::SkOrderedReadBuffer(SkStream* stream) {
+    const size_t length = stream->getLength();
+    fMemoryPtr = sk_malloc_throw(length);
+    stream->read(fMemoryPtr, length);
+    fReader.setMemory(fMemoryPtr, length);
+}
+
+SkOrderedReadBuffer::~SkOrderedReadBuffer() {
+    sk_free(fMemoryPtr);
+}
+
+bool SkOrderedReadBuffer::readBool() {
+    return fReader.readBool();
+}
+
+SkColor SkOrderedReadBuffer::readColor() {
+    return fReader.readInt();
+}
+
+SkFixed SkOrderedReadBuffer::readFixed() {
+    return fReader.readS32();
+}
+
+int32_t SkOrderedReadBuffer::readInt() {
+    return fReader.readInt();
+}
+
+SkScalar SkOrderedReadBuffer::readScalar() {
+    return fReader.readScalar();
+}
+
+uint32_t SkOrderedReadBuffer::readUInt() {
+    return fReader.readU32();
+}
+
+int32_t SkOrderedReadBuffer::read32() {
+    return fReader.readInt();
+}
+
+char* SkOrderedReadBuffer::readString() {
+    const char* string = fReader.readString();
+    const int32_t length = strlen(string);
+    char* value = (char*)sk_malloc_throw(length + 1);
+    strcpy(value, string);
+    return value;
+}
+
+void* SkOrderedReadBuffer::readEncodedString(size_t* length, SkPaint::TextEncoding encoding) {
+    int32_t encodingType = fReader.readInt();
+    SkASSERT(encodingType == encoding);
+    *length =  fReader.readInt();
+    void* data = sk_malloc_throw(*length);
+    memcpy(data, fReader.skip(SkAlign4(*length)), *length);
+    return data;
+}
+
+void SkOrderedReadBuffer::readPoint(SkPoint* point) {
+    point->fX = fReader.readScalar();
+    point->fY = fReader.readScalar();
+}
+
+void SkOrderedReadBuffer::readMatrix(SkMatrix* matrix) {
+    fReader.readMatrix(matrix);
+}
+
+void SkOrderedReadBuffer::readIRect(SkIRect* rect) {
+    memcpy(rect, fReader.skip(sizeof(SkIRect)), sizeof(SkIRect));
+}
+
+void SkOrderedReadBuffer::readRect(SkRect* rect) {
+    memcpy(rect, fReader.skip(sizeof(SkRect)), sizeof(SkRect));
+}
+
+void SkOrderedReadBuffer::readRegion(SkRegion* region) {
+    fReader.readRegion(region);
+}
+
+void SkOrderedReadBuffer::readPath(SkPath* path) {
+    fReader.readPath(path);
+}
+
+uint32_t SkOrderedReadBuffer::readByteArray(void* value) {
+    const uint32_t length = fReader.readU32();
+    memcpy(value, fReader.skip(SkAlign4(length)), length);
+    return length;
+}
+
+uint32_t SkOrderedReadBuffer::readColorArray(SkColor* colors) {
+    const uint32_t count = fReader.readU32();
+    const uint32_t byteLength = count * sizeof(SkColor);
+    memcpy(colors, fReader.skip(SkAlign4(byteLength)), byteLength);
+    return count;
+}
+
+uint32_t SkOrderedReadBuffer::readIntArray(int32_t* values) {
+    const uint32_t count = fReader.readU32();
+    const uint32_t byteLength = count * sizeof(int32_t);
+    memcpy(values, fReader.skip(SkAlign4(byteLength)), byteLength);
+    return count;
+}
+
+uint32_t SkOrderedReadBuffer::readPointArray(SkPoint* points) {
+    const uint32_t count = fReader.readU32();
+    const uint32_t byteLength = count * sizeof(SkPoint);
+    memcpy(points, fReader.skip(SkAlign4(byteLength)), byteLength);
+    return count;
+}
+
+uint32_t SkOrderedReadBuffer::readScalarArray(SkScalar* values) {
+    const uint32_t count = fReader.readU32();
+    const uint32_t byteLength = count * sizeof(SkScalar);
+    memcpy(values, fReader.skip(SkAlign4(byteLength)), byteLength);
+    return count;
+}
+
+uint32_t SkOrderedReadBuffer::getArrayCount() {
+    return *(uint32_t*)fReader.peek();
+}
+
+SkRefCnt* SkOrderedReadBuffer::readRefCntPtr() {
+    if (fRCArray) {
+        const uint32_t index = fReader.readU32();
+        SkASSERT(index <= (unsigned)fRCCount);
+        return fRCArray[index - 1];
+    } else {
+        return INHERITED::readRefCntPtr();
+    }
+}
+
+void SkOrderedReadBuffer::readBitmap(SkBitmap* bitmap) {
+    bitmap->unflatten(*this);
 }
 
 SkTypeface* SkOrderedReadBuffer::readTypeface() {
+
     uint32_t index = fReader.readU32();
     if (0 == index || index > (unsigned)fTFCount) {
         if (index) {
@@ -27,16 +173,6 @@
     }
 }
 
-SkRefCnt* SkOrderedReadBuffer::readRefCnt() {
-    uint32_t index = fReader.readU32();
-    if (0 == index || index > (unsigned)fRCCount) {
-        return NULL;
-    } else {
-        SkASSERT(fRCArray);
-        return fRCArray[index - 1];
-    }
-}
-
 SkFlattenable* SkOrderedReadBuffer::readFlattenable() {
     SkFlattenable::Factory factory = NULL;
 
@@ -81,11 +217,3 @@
     }
     return obj;
 }
-
-void* SkOrderedReadBuffer::readFunctionPtr() {
-    SkASSERT(!this->isCrossProcess());
-
-    void* proc;
-    fReader.read(&proc, sizeof(proc));
-    return proc;
-}
diff --git a/src/core/SkOrderedWriteBuffer.cpp b/src/core/SkOrderedWriteBuffer.cpp
index fdfb6e3..9dd70fb 100644
--- a/src/core/SkOrderedWriteBuffer.cpp
+++ b/src/core/SkOrderedWriteBuffer.cpp
@@ -1,6 +1,6 @@
 
 /*
- * Copyright 2011 Google Inc.
+ * Copyright 2012 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
@@ -9,14 +9,176 @@
 #include "SkOrderedWriteBuffer.h"
 #include "SkTypeface.h"
 
-SkOrderedWriteBuffer::SkOrderedWriteBuffer(size_t minSize) 
-    : fWriter(minSize) {
+SkOrderedWriteBuffer::SkOrderedWriteBuffer(size_t minSize)
+    : INHERITED()
+    , fFactorySet(NULL)
+    , fNamedFactorySet(NULL)
+    , fWriter(minSize)
+    , fRCSet(NULL)
+    , fTFSet(NULL) {
 }
 
-SkOrderedWriteBuffer::SkOrderedWriteBuffer(size_t minSize, 
-                                           void* storage, 
-                                           size_t storageSize)
-    : fWriter(minSize, storage, storageSize) {
+SkOrderedWriteBuffer::SkOrderedWriteBuffer(size_t minSize, void* storage, size_t storageSize)
+    : INHERITED()
+    , fFactorySet(NULL)
+    , fNamedFactorySet(NULL)
+    , fWriter(minSize, storage, storageSize)
+    , fRCSet(NULL)
+    , fTFSet(NULL) {
+}
+
+SkOrderedWriteBuffer::~SkOrderedWriteBuffer() {
+    SkSafeUnref(fFactorySet);
+    SkSafeUnref(fNamedFactorySet);
+    SkSafeUnref(fRCSet);
+    SkSafeUnref(fTFSet);
+}
+
+void SkOrderedWriteBuffer::writeByteArray(const void* data, size_t size) {
+    fWriter.write32(size);
+    fWriter.writePad(data, size);
+}
+
+void SkOrderedWriteBuffer::writeBool(bool value) {
+    fWriter.writeBool(value);
+}
+
+void SkOrderedWriteBuffer::writeFixed(SkFixed value) {
+    fWriter.write32(value);
+}
+
+void SkOrderedWriteBuffer::writeScalar(SkScalar value) {
+    fWriter.writeScalar(value);
+}
+
+void SkOrderedWriteBuffer::writeScalarArray(const SkScalar* value, uint32_t count) {
+    fWriter.write32(count);
+    fWriter.write(value, count * sizeof(SkScalar));
+}
+
+void SkOrderedWriteBuffer::writeInt(int32_t value) {
+    fWriter.write32(value);
+}
+
+void SkOrderedWriteBuffer::writeIntArray(const int32_t* value, uint32_t count) {
+    fWriter.write32(count);
+    fWriter.write(value, count * sizeof(int32_t));
+}
+
+void SkOrderedWriteBuffer::writeUInt(uint32_t value) {
+    fWriter.write32(value);
+}
+
+void SkOrderedWriteBuffer::write32(int32_t value) {
+    fWriter.write32(value);
+}
+
+void SkOrderedWriteBuffer::writeString(const char* value) {
+    fWriter.writeString(value);
+}
+
+void SkOrderedWriteBuffer::writeEncodedString(const void* value, size_t byteLength,
+                                              SkPaint::TextEncoding encoding) {
+    fWriter.writeInt(encoding);
+    fWriter.writeInt(byteLength);
+    fWriter.write(value, byteLength);
+}
+
+
+void SkOrderedWriteBuffer::writeColor(const SkColor& color) {
+    fWriter.write32(color);
+}
+
+void SkOrderedWriteBuffer::writeColorArray(const SkColor* color, uint32_t count) {
+    fWriter.write32(count);
+    fWriter.write(color, count * sizeof(SkColor));
+}
+
+void SkOrderedWriteBuffer::writePoint(const SkPoint& point) {
+    fWriter.writeScalar(point.fX);
+    fWriter.writeScalar(point.fY);
+}
+
+void SkOrderedWriteBuffer::writePointArray(const SkPoint* point, uint32_t count) {
+    fWriter.write32(count);
+    fWriter.write(point, count * sizeof(SkPoint));
+}
+
+void SkOrderedWriteBuffer::writeMatrix(const SkMatrix& matrix) {
+    fWriter.writeMatrix(matrix);
+}
+
+void SkOrderedWriteBuffer::writeIRect(const SkIRect& rect) {
+    fWriter.write(&rect, sizeof(SkIRect));
+}
+
+void SkOrderedWriteBuffer::writeRect(const SkRect& rect) {
+    fWriter.writeRect(rect);
+}
+
+void SkOrderedWriteBuffer::writeRegion(const SkRegion& region) {
+    fWriter.writeRegion(region);
+}
+
+void SkOrderedWriteBuffer::writePath(const SkPath& path) {
+    fWriter.writePath(path);
+}
+
+size_t SkOrderedWriteBuffer::writeStream(SkStream* stream, size_t length) {
+    return fWriter.readFromStream(stream, length);
+}
+
+bool SkOrderedWriteBuffer::writeToStream(SkWStream* stream) {
+    return fWriter.writeToStream(stream);
+}
+
+void SkOrderedWriteBuffer::writeRefCntPtr(SkRefCnt* refCnt) {
+    SkASSERT(!isCrossProcess());
+    if (NULL == fRCSet) {
+        INHERITED::writeRefCntPtr(refCnt);
+    } else {
+        this->write32(fRCSet->add(refCnt));
+    }
+}
+
+void SkOrderedWriteBuffer::writeBitmap(const SkBitmap& bitmap) {
+    bitmap.flatten(*this);
+}
+
+void SkOrderedWriteBuffer::writeTypeface(SkTypeface* obj) {
+    if (NULL == obj || NULL == fTFSet) {
+        fWriter.write32(0);
+    } else {
+        fWriter.write32(fTFSet->add(obj));
+    }
+}
+
+SkFactorySet* SkOrderedWriteBuffer::setFactoryRecorder(SkFactorySet* rec) {
+    SkRefCnt_SafeAssign(fFactorySet, rec);
+    if (fNamedFactorySet != NULL) {
+        fNamedFactorySet->unref();
+        fNamedFactorySet = NULL;
+    }
+    return rec;
+}
+
+SkNamedFactorySet* SkOrderedWriteBuffer::setNamedFactoryRecorder(SkNamedFactorySet* rec) {
+    SkRefCnt_SafeAssign(fNamedFactorySet, rec);
+    if (fFactorySet != NULL) {
+        fFactorySet->unref();
+        fFactorySet = NULL;
+    }
+    return rec;
+}
+
+SkRefCntSet* SkOrderedWriteBuffer::setRefCntRecorder(SkRefCntSet* rec) {
+    SkRefCnt_SafeAssign(fRCSet, rec);
+    return rec;
+}
+
+SkRefCntSet* SkOrderedWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) {
+    SkRefCnt_SafeAssign(fTFSet, rec);
+    return rec;
 }
 
 void SkOrderedWriteBuffer::writeFlattenable(SkFlattenable* flattenable) {
@@ -69,18 +231,12 @@
     }
 
     // make room for the size of the flatttened object
-    (void)this->reserve(sizeof(uint32_t));
+    (void)fWriter.reserve(sizeof(uint32_t));
     // record the current size, so we can subtract after the object writes.
-    uint32_t offset = this->size();
+    uint32_t offset = fWriter.size();
     // now flatten the object
     flattenObject(flattenable, *this);
-    uint32_t objSize = this->size() - offset;
+    uint32_t objSize = fWriter.size() - offset;
     // record the obj's size
     *fWriter.peek32(offset - sizeof(uint32_t)) = objSize;
 }
-
-void SkOrderedWriteBuffer::writeFunctionPtr(void* proc) {
-    SkASSERT(!this->isCrossProcess());
-
-    *(void**)this->reserve(sizeof(void*)) = proc;
-}
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index ae5d0b2..2cfb67b 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -26,6 +26,7 @@
 #include "SkAutoKern.h"
 #include "SkGlyphCache.h"
 #include "SkPaintDefaults.h"
+#include "SkOrderedReadBuffer.h"
 #include "SkOrderedWriteBuffer.h"
 
 // define this to get a printf for out-of-range parameter in setters
@@ -1392,8 +1393,8 @@
 }
 
 static void add_flattenable(SkDescriptor* desc, uint32_t tag,
-                            SkFlattenableWriteBuffer* buffer) {
-    buffer->flatten(desc->addEntry(tag, buffer->size(), NULL));
+                            SkOrderedWriteBuffer* buffer) {
+    buffer->writeToMemory(desc->addEntry(tag, buffer->size(), NULL));
 }
 
 // SkFontHost can override this choice in FilterRec()
@@ -1932,24 +1933,43 @@
         flatFlags |= kHasEffects_FlatFlag;
     }
 
-    SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
-    uint32_t* ptr = buffer.reserve(kPODPaintSize);
 
-    ptr = write_scalar(ptr, this->getTextSize());
-    ptr = write_scalar(ptr, this->getTextScaleX());
-    ptr = write_scalar(ptr, this->getTextSkewX());
-    ptr = write_scalar(ptr, this->getStrokeWidth());
-    ptr = write_scalar(ptr, this->getStrokeMiter());
-    *ptr++ = this->getColor();
-    // previously flags:16, textAlign:8, flatFlags:8
-    // now flags:16, hinting:4, textAlign:4, flatFlags:8
-    *ptr++ = (this->getFlags() << 16) |
-             // hinting added later. 0 in this nibble means use the default.
-             ((this->getHinting()+1) << 12) |
-             (this->getTextAlign() << 8) |
-             flatFlags;
-    *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(),
-                    this->getStyle(), this->getTextEncoding());
+    if (buffer.isOrderedBinaryBuffer()) {
+        SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
+        uint32_t* ptr = buffer.getOrderedBinaryBuffer()->reserve(kPODPaintSize);
+
+        ptr = write_scalar(ptr, this->getTextSize());
+        ptr = write_scalar(ptr, this->getTextScaleX());
+        ptr = write_scalar(ptr, this->getTextSkewX());
+        ptr = write_scalar(ptr, this->getStrokeWidth());
+        ptr = write_scalar(ptr, this->getStrokeMiter());
+        *ptr++ = this->getColor();
+        // previously flags:16, textAlign:8, flatFlags:8
+        // now flags:16, hinting:4, textAlign:4, flatFlags:8
+        *ptr++ = (this->getFlags() << 16) |
+                 // hinting added later. 0 in this nibble means use the default.
+                 ((this->getHinting()+1) << 12) |
+                 (this->getTextAlign() << 8) |
+                 flatFlags;
+        *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(),
+                        this->getStyle(), this->getTextEncoding());
+    } else {
+        buffer.writeScalar(fTextSize);
+        buffer.writeScalar(fTextScaleX);
+        buffer.writeScalar(fTextSkewX);
+        buffer.writeScalar(fWidth);
+        buffer.writeScalar(fMiterLimit);
+        buffer.writeColor(fColor);
+        buffer.writeUInt(fFlags);
+        buffer.writeUInt(fHinting);
+        buffer.writeUInt(fTextAlign);
+        buffer.writeUInt(flatFlags);
+
+        buffer.writeUInt(fCapType);
+        buffer.writeUInt(fJoinType);
+        buffer.writeUInt(fStyle);
+        buffer.writeUInt(fTextEncoding);
+    }
 
     // now we're done with ptr and the (pre)reserved space. If we need to write
     // additional fields, use the buffer directly
@@ -1970,38 +1990,57 @@
 }
 
 void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) {
-    SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
-    const void* podData = buffer.skip(kPODPaintSize);
-    const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData);
-
     fPrivFlags = 0;
 
-    // the order we read must match the order we wrote in flatten()
-    this->setTextSize(read_scalar(pod));
-    this->setTextScaleX(read_scalar(pod));
-    this->setTextSkewX(read_scalar(pod));
-    this->setStrokeWidth(read_scalar(pod));
-    this->setStrokeMiter(read_scalar(pod));
-    this->setColor(*pod++);
+    uint8_t flatFlags = 0;
+    if (buffer.isOrderedBinaryBuffer()) {
+        SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
+        const void* podData = buffer.getOrderedBinaryBuffer()->skip(kPODPaintSize);
+        const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData);
 
-    // previously flags:16, textAlign:8, flatFlags:8
-    // now flags:16, hinting:4, textAlign:4, flatFlags:8
-    uint32_t tmp = *pod++;
-    this->setFlags(tmp >> 16);
+        // the order we read must match the order we wrote in flatten()
+        this->setTextSize(read_scalar(pod));
+        this->setTextScaleX(read_scalar(pod));
+        this->setTextSkewX(read_scalar(pod));
+        this->setStrokeWidth(read_scalar(pod));
+        this->setStrokeMiter(read_scalar(pod));
+        this->setColor(*pod++);
 
-    // hinting added later. 0 in this nibble means use the default.
-    uint32_t hinting = (tmp >> 12) & 0xF;
-    this->setHinting(0 == hinting ? kNormal_Hinting : static_cast<Hinting>(hinting-1));
+        // previously flags:16, textAlign:8, flatFlags:8
+        // now flags:16, hinting:4, textAlign:4, flatFlags:8
+        uint32_t tmp = *pod++;
+        this->setFlags(tmp >> 16);
 
-    this->setTextAlign(static_cast<Align>((tmp >> 8) & 0xF));
+        // hinting added later. 0 in this nibble means use the default.
+        uint32_t hinting = (tmp >> 12) & 0xF;
+        this->setHinting(0 == hinting ? kNormal_Hinting : static_cast<Hinting>(hinting-1));
 
-    uint8_t flatFlags = tmp & 0xFF;
+        this->setTextAlign(static_cast<Align>((tmp >> 8) & 0xF));
 
-    tmp = *pod++;
-    this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF));
-    this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF));
-    this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
-    this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
+        flatFlags = tmp & 0xFF;
+
+        tmp = *pod++;
+        this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF));
+        this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF));
+        this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
+        this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
+    } else {
+        this->setTextSize(buffer.readScalar());
+        this->setTextScaleX(buffer.readScalar());
+        this->setTextSkewX(buffer.readScalar());
+        this->setStrokeWidth(buffer.readScalar());
+        this->setStrokeMiter(buffer.readScalar());
+        this->setColor(buffer.readColor());
+        this->setFlags(buffer.readUInt());
+        this->setHinting(static_cast<SkPaint::Hinting>(buffer.readUInt()));
+        this->setTextAlign(static_cast<SkPaint::Align>(buffer.readUInt()));
+        flatFlags = buffer.readUInt();
+
+        this->setStrokeCap(static_cast<SkPaint::Cap>(buffer.readUInt()));
+        this->setStrokeJoin(static_cast<SkPaint::Join>(buffer.readUInt()));
+        this->setStyle(static_cast<SkPaint::Style>(buffer.readUInt()));
+        this->setTextEncoding(static_cast<SkPaint::TextEncoding>(buffer.readUInt()));
+    }
 
     if (flatFlags & kHasTypeface_FlatFlag) {
         this->setTypeface(buffer.readTypeface());
@@ -2010,15 +2049,15 @@
     }
 
     if (flatFlags & kHasEffects_FlatFlag) {
-        SkSafeUnref(this->setPathEffect((SkPathEffect*) buffer.readFlattenable()));
-        SkSafeUnref(this->setShader((SkShader*) buffer.readFlattenable()));
-        SkSafeUnref(this->setXfermode((SkXfermode*) buffer.readFlattenable()));
-        SkSafeUnref(this->setMaskFilter((SkMaskFilter*) buffer.readFlattenable()));
-        SkSafeUnref(this->setColorFilter((SkColorFilter*) buffer.readFlattenable()));
-        SkSafeUnref(this->setRasterizer((SkRasterizer*) buffer.readFlattenable()));
-        SkSafeUnref(this->setLooper((SkDrawLooper*) buffer.readFlattenable()));
-        SkSafeUnref(this->setImageFilter((SkImageFilter*) buffer.readFlattenable()));
-        SkSafeUnref(this->setAnnotation((SkAnnotation*) buffer.readFlattenable()));
+        SkSafeUnref(this->setPathEffect(buffer.readFlattenableT<SkPathEffect>()));
+        SkSafeUnref(this->setShader(buffer.readFlattenableT<SkShader>()));
+        SkSafeUnref(this->setXfermode(buffer.readFlattenableT<SkXfermode>()));
+        SkSafeUnref(this->setMaskFilter(buffer.readFlattenableT<SkMaskFilter>()));
+        SkSafeUnref(this->setColorFilter(buffer.readFlattenableT<SkColorFilter>()));
+        SkSafeUnref(this->setRasterizer(buffer.readFlattenableT<SkRasterizer>()));
+        SkSafeUnref(this->setLooper(buffer.readFlattenableT<SkDrawLooper>()));
+        SkSafeUnref(this->setImageFilter(buffer.readFlattenableT<SkImageFilter>()));
+        SkSafeUnref(this->setAnnotation(buffer.readFlattenableT<SkAnnotation>()));
     } else {
         this->setPathEffect(NULL);
         this->setShader(NULL);
diff --git a/src/core/SkPathEffect.cpp b/src/core/SkPathEffect.cpp
index 8708e7e..6abce74 100644
--- a/src/core/SkPathEffect.cpp
+++ b/src/core/SkPathEffect.cpp
@@ -10,6 +10,7 @@
 #include "SkPathEffect.h"
 #include "SkPath.h"
 #include "SkBuffer.h"
+#include "SkFlattenableBuffers.h"
 #include "SkPaintDefaults.h"
 
 // must be < 0, since ==0 means hairline, and >0 means normal stroke
@@ -141,8 +142,8 @@
 }
 
 SkPairPathEffect::SkPairPathEffect(SkFlattenableReadBuffer& buffer) {
-    fPE0 = (SkPathEffect*)buffer.readFlattenable();
-    fPE1 = (SkPathEffect*)buffer.readFlattenable();
+    fPE0 = buffer.readFlattenableT<SkPathEffect>();
+    fPE1 = buffer.readFlattenableT<SkPathEffect>();
     // either of these may fail, so we have to check for nulls later on
 }
 
diff --git a/src/core/SkPathHeap.cpp b/src/core/SkPathHeap.cpp
index 8713e76..3add392 100644
--- a/src/core/SkPathHeap.cpp
+++ b/src/core/SkPathHeap.cpp
@@ -8,7 +8,7 @@
 #include "SkPathHeap.h"
 #include "SkPath.h"
 #include "SkStream.h"
-#include "SkFlattenable.h"
+#include "SkFlattenableBuffers.h"
 #include <new>
 
 SK_DEFINE_INST_COUNT(SkPathHeap)
@@ -20,7 +20,7 @@
 
 SkPathHeap::SkPathHeap(SkFlattenableReadBuffer& buffer)
             : fHeap(kPathCount * sizeof(SkPath)) {
-    int count = buffer.readS32();
+    const int count = buffer.readInt();
 
     fPaths.setCount(count);
     SkPath** ptr = fPaths.begin();
@@ -53,7 +53,7 @@
 void SkPathHeap::flatten(SkFlattenableWriteBuffer& buffer) const {
     int count = fPaths.count();
     
-    buffer.write32(count);
+    buffer.writeInt(count);
     SkPath** iter = fPaths.begin();
     SkPath** stop = fPaths.end();
     while (iter < stop) {
diff --git a/src/core/SkPictureFlat.cpp b/src/core/SkPictureFlat.cpp
index fa65ca4..a593e36 100644
--- a/src/core/SkPictureFlat.cpp
+++ b/src/core/SkPictureFlat.cpp
@@ -126,7 +126,7 @@
     result->fFlatSize = size;
 
     // put the serialized contents into the data section of the new allocation
-    buffer.flatten(result->data());
+    buffer.writeToMemory(result->data());
     result->fChecksum = SkChecksum::Compute(result->data32(), size);
     result->setSentinelAsCandidate();
     return result;
diff --git a/src/core/SkPictureFlat.h b/src/core/SkPictureFlat.h
index dbec5c9..c4605aa 100644
--- a/src/core/SkPictureFlat.h
+++ b/src/core/SkPictureFlat.h
@@ -95,7 +95,7 @@
     void setCount(int count);
     SkRefCnt* set(int index, SkRefCnt*);
 
-    virtual void setupBuffer(SkFlattenableReadBuffer& buffer) const {
+    virtual void setupBuffer(SkOrderedReadBuffer& buffer) const {
         buffer.setRefCntArray(fArray, fCount);
     }
     
@@ -106,7 +106,7 @@
 
 class SkTypefacePlayback : public SkRefCntPlayback {
 public:
-    virtual void setupBuffer(SkFlattenableReadBuffer& buffer) const {
+    virtual void setupBuffer(SkOrderedReadBuffer& buffer) const {
         buffer.setTypefaceArray((SkTypeface**)fArray, fCount);
     }
 };
@@ -123,7 +123,7 @@
     
     SkFlattenable::Factory* base() const { return fArray; }
 
-    void setupBuffer(SkFlattenableReadBuffer& buffer) const {
+    void setupBuffer(SkOrderedReadBuffer& buffer) const {
         buffer.setFactoryPlayback(fArray, fCount);
     }
     
diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp
index c4c40c1..f05aeaa 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -206,10 +206,10 @@
 
 #include "SkStream.h"
 
-static void writeTagSize(SkFlattenableWriteBuffer& buffer, uint32_t tag,
+static void writeTagSize(SkOrderedWriteBuffer& buffer, uint32_t tag,
                          uint32_t size) {
-    buffer.write32(tag);
-    buffer.write32(size);
+    buffer.writeUInt(tag);
+    buffer.writeUInt(size);
 }
 
 static void writeTagSize(SkWStream* stream, uint32_t tag,
@@ -260,19 +260,22 @@
     if ((n = SafeCount(fBitmaps)) > 0) {
         writeTagSize(buffer, PICT_BITMAP_BUFFER_TAG, n);
         for (i = 0; i < n; i++) {
-            (*fBitmaps)[i].flatten(buffer);
+            buffer.writeBitmap((*fBitmaps)[i]);
         }
     }
     
     if ((n = SafeCount(fMatrices)) > 0) {
         writeTagSize(buffer, PICT_MATRIX_BUFFER_TAG, n);
-        buffer.writeMul4(fMatrices->begin(), n * sizeof(SkMatrix));
+        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++) {
-            (*fPaints)[i].flatten(buffer);
+            buffer.writePaint((*fPaints)[i]);
         }
     }
     
@@ -284,7 +287,7 @@
     if ((n = SafeCount(fRegions)) > 0) {
         writeTagSize(buffer, PICT_REGION_BUFFER_TAG, n);
         for (i = 0; i < n; i++) {
-            buffer.getWriter32()->writeRegion((*fRegions)[i]);
+            buffer.writeRegion((*fRegions)[i]);
         }
     }
 }
@@ -408,8 +411,8 @@
             fTFPlayback.setupBuffer(buffer);
             
             while (!buffer.eof()) {
-                tag = buffer.readU32();
-                size = buffer.readU32();
+                tag = buffer.readUInt();
+                size = buffer.readUInt();
                 if (!this->parseBufferTag(buffer, tag, size)) {
                     return false;
                 }
@@ -426,17 +429,19 @@
         case PICT_BITMAP_BUFFER_TAG: {
             fBitmaps = SkTRefArray<SkBitmap>::Create(size);
             for (size_t i = 0; i < size; ++i) {
-                fBitmaps->writableAt(i).unflatten(buffer);
+                buffer.readBitmap(&fBitmaps->writableAt(i));
             }
         } break;
         case PICT_MATRIX_BUFFER_TAG:
             fMatrices = SkTRefArray<SkMatrix>::Create(size);
-            buffer.read(&fMatrices->writableAt(0), size * sizeof(SkMatrix));
+            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) {
-                fPaints->writableAt(i).unflatten(buffer);
+                buffer.readPaint(&fPaints->writableAt(i));
             }
         } break;
         case PICT_PATH_BUFFER_TAG:
@@ -447,7 +452,7 @@
         case PICT_REGION_BUFFER_TAG: {
             fRegions = SkTRefArray<SkRegion>::Create(size);
             for (size_t i = 0; i < size; ++i) {
-                buffer.getReader32()->readRegion(&fRegions->writableAt(i));
+                buffer.readRegion(&fRegions->writableAt(i));
             }
         } break;
     }
diff --git a/src/core/SkPixelRef.cpp b/src/core/SkPixelRef.cpp
index a5ae6df..d02f504 100644
--- a/src/core/SkPixelRef.cpp
+++ b/src/core/SkPixelRef.cpp
@@ -6,7 +6,7 @@
  * found in the LICENSE file.
  */
 #include "SkPixelRef.h"
-#include "SkFlattenable.h"
+#include "SkFlattenableBuffers.h"
 #include "SkThread.h"
 
 SK_DEFINE_INST_COUNT(SkPixelRef)
@@ -74,7 +74,7 @@
     fColorTable = NULL; // we do not track ownership of this
     fLockCount = 0;
     fIsImmutable = buffer.readBool();
-    fGenerationID = buffer.readU32();
+    fGenerationID = buffer.readUInt();
     fPreLocked = false;
 }
 
@@ -96,9 +96,9 @@
     // of genIDs. So for cross-process recording we write a zero which will
     // trigger assignment of a new genID in playback.
     if (buffer.isCrossProcess()) {
-        buffer.write32(0);
+        buffer.writeUInt(0);
     } else {
-        buffer.write32(fGenerationID);
+        buffer.writeUInt(fGenerationID);
     }
 }
 
diff --git a/src/core/SkShader.cpp b/src/core/SkShader.cpp
index cf522b6..92a5d3f 100644
--- a/src/core/SkShader.cpp
+++ b/src/core/SkShader.cpp
@@ -9,6 +9,7 @@
 
 #include "SkScalar.h"
 #include "SkShader.h"
+#include "SkFlattenableBuffers.h"
 #include "SkPaint.h"
 #include "SkMallocPixelRef.h"
 
@@ -238,20 +239,20 @@
 SkColorShader::SkColorShader(SkFlattenableReadBuffer& b) : INHERITED(b) {
     fFlags = 0; // computed in setContext
 
-    fInheritColor = b.readU8();
+    fInheritColor = b.readBool();
     if (fInheritColor) {
         return;
     }
-    fColor = b.readU32();
+    fColor = b.readColor();
 }
 
 void SkColorShader::flatten(SkFlattenableWriteBuffer& buffer) const {
     this->INHERITED::flatten(buffer);
-    buffer.write8(fInheritColor);
+    buffer.writeBool(fInheritColor);
     if (fInheritColor) {
         return;
     }
-    buffer.write32(fColor);
+    buffer.writeColor(fColor);
 }
 
 uint32_t SkColorShader::getFlags() {
diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp
index 03f996a..74097be 100644
--- a/src/core/SkXfermode.cpp
+++ b/src/core/SkXfermode.cpp
@@ -9,6 +9,7 @@
 
 #include "SkXfermode.h"
 #include "SkColorPriv.h"
+#include "SkFlattenableBuffers.h"
 
 SK_DEFINE_INST_COUNT(SkXfermode)
 
@@ -734,7 +735,7 @@
 
 protected:
     SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
-        fMode = (SkXfermode::Mode)buffer.readU32();
+        fMode = (SkXfermode::Mode)buffer.read32();
 
         const ProcCoeff& rec = gProcCoeffs[fMode];
         // these may be valid, or may be CANNOT_USE_COEFF