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
diff --git a/src/effects/Sk1DPathEffect.cpp b/src/effects/Sk1DPathEffect.cpp
index 10a9a84..a176cf8 100644
--- a/src/effects/Sk1DPathEffect.cpp
+++ b/src/effects/Sk1DPathEffect.cpp
@@ -8,6 +8,7 @@
 
 
 #include "Sk1DPathEffect.h"
+#include "SkFlattenableBuffers.h"
 #include "SkPathMeasure.h"
 
 bool Sk1DPathEffect::filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*) {
@@ -149,7 +150,7 @@
     if (fAdvance > 0) {
         buffer.readPath(&fPath);
         fInitialOffset = buffer.readScalar();
-        fStyle = (Style) buffer.readU8();
+        fStyle = (Style) buffer.readUInt();
     } else {
         SkDEBUGF(("SkPath1DPathEffect can't use advance <= 0\n"));
         // Make Coverity happy.
@@ -168,7 +169,7 @@
     if (fAdvance > 0) {
         buffer.writePath(fPath);
         buffer.writeScalar(fInitialOffset);
-        buffer.write8(fStyle);
+        buffer.writeUInt(fStyle);
     }
 }
 
diff --git a/src/effects/Sk2DPathEffect.cpp b/src/effects/Sk2DPathEffect.cpp
index e19cdeb..1a09a92 100644
--- a/src/effects/Sk2DPathEffect.cpp
+++ b/src/effects/Sk2DPathEffect.cpp
@@ -9,6 +9,7 @@
 
 #include "Sk2DPathEffect.h"
 #include "SkBlitter.h"
+#include "SkFlattenableBuffers.h"
 #include "SkPath.h"
 #include "SkScan.h"
 
diff --git a/src/effects/SkAvoidXfermode.cpp b/src/effects/SkAvoidXfermode.cpp
index b5375e6..f828cca 100644
--- a/src/effects/SkAvoidXfermode.cpp
+++ b/src/effects/SkAvoidXfermode.cpp
@@ -9,6 +9,7 @@
 
 #include "SkAvoidXfermode.h"
 #include "SkColorPriv.h"
+#include "SkFlattenableBuffers.h"
 
 SkAvoidXfermode::SkAvoidXfermode(SkColor opColor, U8CPU tolerance, Mode mode)
 {
@@ -24,18 +25,18 @@
 SkAvoidXfermode::SkAvoidXfermode(SkFlattenableReadBuffer& buffer)
     : INHERITED(buffer)
 {
-    fOpColor = buffer.readU32();
-    fDistMul = buffer.readU32();
-    fMode = (Mode)buffer.readU8();
+    fOpColor = buffer.readColor();
+    fDistMul = buffer.readUInt();
+    fMode = (Mode)buffer.readUInt();
 }
 
 void SkAvoidXfermode::flatten(SkFlattenableWriteBuffer& buffer) const
 {
     this->INHERITED::flatten(buffer);
 
-    buffer.write32(fOpColor);
-    buffer.write32(fDistMul);
-    buffer.write8(fMode);
+    buffer.writeColor(fOpColor);
+    buffer.writeUInt(fDistMul);
+    buffer.writeUInt(fMode);
 }
 
 // returns 0..31
diff --git a/src/effects/SkBlurDrawLooper.cpp b/src/effects/SkBlurDrawLooper.cpp
index 3b78573..9ec2aff 100644
--- a/src/effects/SkBlurDrawLooper.cpp
+++ b/src/effects/SkBlurDrawLooper.cpp
@@ -8,6 +8,7 @@
 #include "SkBlurDrawLooper.h"
 #include "SkBlurMaskFilter.h"
 #include "SkCanvas.h"
+#include "SkFlattenableBuffers.h"
 #include "SkPaint.h"
 #include "SkMaskFilter.h"
 #include "SkColorFilter.h"
@@ -50,10 +51,10 @@
 
     fDx = buffer.readScalar();
     fDy = buffer.readScalar();
-    fBlurColor = buffer.readU32();
-    fBlur = static_cast<SkMaskFilter*>(buffer.readFlattenable());
-    fColorFilter = static_cast<SkColorFilter*>(buffer.readFlattenable());
-    fBlurFlags = buffer.readU32() & kAll_BlurFlag;
+    fBlurColor = buffer.readColor();
+    fBlur = buffer.readFlattenableT<SkMaskFilter>();
+    fColorFilter = buffer.readFlattenableT<SkColorFilter>();
+    fBlurFlags = buffer.readUInt() & kAll_BlurFlag;
 }
 
 SkBlurDrawLooper::~SkBlurDrawLooper() {
@@ -65,10 +66,10 @@
     this->INHERITED::flatten(buffer);
     buffer.writeScalar(fDx);
     buffer.writeScalar(fDy);
-    buffer.write32(fBlurColor);
+    buffer.writeColor(fBlurColor);
     buffer.writeFlattenable(fBlur);
     buffer.writeFlattenable(fColorFilter);
-    buffer.write32(fBlurFlags);
+    buffer.writeUInt(fBlurFlags);
 }
 
 void SkBlurDrawLooper::init(SkCanvas* canvas) {
diff --git a/src/effects/SkBlurImageFilter.cpp b/src/effects/SkBlurImageFilter.cpp
index f3e96e0..b01795b 100644
--- a/src/effects/SkBlurImageFilter.cpp
+++ b/src/effects/SkBlurImageFilter.cpp
@@ -8,6 +8,7 @@
 #include "SkBitmap.h"
 #include "SkBlurImageFilter.h"
 #include "SkColorPriv.h"
+#include "SkFlattenableBuffers.h"
 #if SK_SUPPORT_GPU
 #include "GrContext.h"
 #endif
diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp
index 306770b..6424732 100644
--- a/src/effects/SkBlurMaskFilter.cpp
+++ b/src/effects/SkBlurMaskFilter.cpp
@@ -10,6 +10,7 @@
 #include "SkBlurMaskFilter.h"
 #include "SkBlurMask.h"
 #include "SkBuffer.h"
+#include "SkFlattenableBuffers.h"
 #include "SkMaskFilter.h"
 
 class SkBlurMaskFilterImpl : public SkMaskFilter {
@@ -104,8 +105,8 @@
 SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkFlattenableReadBuffer& buffer)
         : SkMaskFilter(buffer) {
     fRadius = buffer.readScalar();
-    fBlurStyle = (SkBlurMaskFilter::BlurStyle)buffer.readS32();
-    fBlurFlags = buffer.readU32() & SkBlurMaskFilter::kAll_BlurFlag;
+    fBlurStyle = (SkBlurMaskFilter::BlurStyle)buffer.readInt();
+    fBlurFlags = buffer.readUInt() & SkBlurMaskFilter::kAll_BlurFlag;
     SkASSERT(fRadius >= 0);
     SkASSERT((unsigned)fBlurStyle < SkBlurMaskFilter::kBlurStyleCount);
 }
@@ -113,8 +114,8 @@
 void SkBlurMaskFilterImpl::flatten(SkFlattenableWriteBuffer& buffer) const {
     this->INHERITED::flatten(buffer);
     buffer.writeScalar(fRadius);
-    buffer.write32(fBlurStyle);
-    buffer.write32(fBlurFlags);
+    buffer.writeInt(fBlurStyle);
+    buffer.writeUInt(fBlurFlags);
 }
 
 static const SkMaskFilter::BlurType gBlurStyle2BlurType[] = {
diff --git a/src/effects/SkColorFilters.cpp b/src/effects/SkColorFilters.cpp
index 78ef0f7..2862f8b 100644
--- a/src/effects/SkColorFilters.cpp
+++ b/src/effects/SkColorFilters.cpp
@@ -10,6 +10,7 @@
 #include "SkBlitRow.h"
 #include "SkColorFilter.h"
 #include "SkColorPriv.h"
+#include "SkFlattenableBuffers.h"
 #include "SkUtils.h"
 
 #define ILLEGAL_XFERMODE_MODE   ((SkXfermode::Mode)-1)
@@ -79,13 +80,13 @@
 protected:
     virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
         this->INHERITED::flatten(buffer);
-        buffer.write32(fColor);
-        buffer.write32(fMode);
+        buffer.writeColor(fColor);
+        buffer.writeUInt(fMode);
     }
 
     SkModeColorFilter(SkFlattenableReadBuffer& buffer) {
-        fColor = buffer.readU32();
-        fMode = (SkXfermode::Mode)buffer.readU32();
+        fColor = buffer.readColor();
+        fMode = (SkXfermode::Mode)buffer.readUInt();
         this->updateCache();
     }
 
@@ -265,13 +266,13 @@
 protected:
     virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
         this->INHERITED::flatten(buffer);
-        buffer.write32(fMul);
-        buffer.write32(fAdd);
+        buffer.writeColor(fMul);
+        buffer.writeColor(fAdd);
     }
 
     SkLightingColorFilter(SkFlattenableReadBuffer& buffer) {
-        fMul = buffer.readU32();
-        fAdd = buffer.readU32();
+        fMul = buffer.readColor();
+        fAdd = buffer.readColor();
     }
 
     SkColor fMul, fAdd;
diff --git a/src/effects/SkColorMatrix.cpp b/src/effects/SkColorMatrix.cpp
index cb77de1..5f6cfd4 100644
--- a/src/effects/SkColorMatrix.cpp
+++ b/src/effects/SkColorMatrix.cpp
@@ -6,6 +6,7 @@
  * found in the LICENSE file.
  */
 #include "SkColorMatrix.h"
+#include "SkFlattenableBuffers.h"
 
 #define kRScale     0
 #define kGScale     6
diff --git a/src/effects/SkColorMatrixFilter.cpp b/src/effects/SkColorMatrixFilter.cpp
index 534bc01..64283ab 100644
--- a/src/effects/SkColorMatrixFilter.cpp
+++ b/src/effects/SkColorMatrixFilter.cpp
@@ -8,6 +8,7 @@
 #include "SkColorMatrixFilter.h"
 #include "SkColorMatrix.h"
 #include "SkColorPriv.h"
+#include "SkFlattenableBuffers.h"
 #include "SkUnPreMultiply.h"
 
 static int32_t rowmul4(const int32_t array[], unsigned r, unsigned g,
@@ -299,14 +300,14 @@
 
 void SkColorMatrixFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
     this->INHERITED::flatten(buffer);
-    // TODO: buffer.writeScalars(array, N)?
-    buffer.write(fMatrix.fMat, sizeof(fMatrix.fMat));
+    SkASSERT(sizeof(fMatrix.fMat)/sizeof(SkScalar) == 20);
+    buffer.writeScalarArray(fMatrix.fMat, 20);
 }
 
 SkColorMatrixFilter::SkColorMatrixFilter(SkFlattenableReadBuffer& buffer)
         : INHERITED(buffer) {
-    // TODO: buffer.readScalars(array, N)?
-    buffer.read(fMatrix.fMat, sizeof(fMatrix.fMat));
+    SkASSERT(buffer.getArrayCount() == 20);
+    buffer.readScalarArray(fMatrix.fMat);
     this->initState(fMatrix.fMat);
 }
 
diff --git a/src/effects/SkCornerPathEffect.cpp b/src/effects/SkCornerPathEffect.cpp
index 749384d..449122f 100644
--- a/src/effects/SkCornerPathEffect.cpp
+++ b/src/effects/SkCornerPathEffect.cpp
@@ -11,6 +11,7 @@
 #include "SkPath.h"
 #include "SkPoint.h"
 #include "SkBuffer.h"
+#include "SkFlattenableBuffers.h"
 
 SkCornerPathEffect::SkCornerPathEffect(SkScalar radius) : fRadius(radius)
 {
diff --git a/src/effects/SkDashPathEffect.cpp b/src/effects/SkDashPathEffect.cpp
index c1bb705..537601f 100644
--- a/src/effects/SkDashPathEffect.cpp
+++ b/src/effects/SkDashPathEffect.cpp
@@ -9,6 +9,7 @@
 
 #include "SkDashPathEffect.h"
 #include "SkBuffer.h"
+#include "SkFlattenableBuffers.h"
 #include "SkPathMeasure.h"
 
 static inline int is_even(int x) {
@@ -235,27 +236,26 @@
     SkASSERT(fInitialDashLength >= 0);
 
     this->INHERITED::flatten(buffer);
-    buffer.write32(fCount);
-    buffer.write32(fInitialDashIndex);
+    buffer.writeInt(fInitialDashIndex);
     buffer.writeScalar(fInitialDashLength);
     buffer.writeScalar(fIntervalLength);
-    buffer.write32(fScaleToFit);
-    buffer.writeMul4(fIntervals, fCount * sizeof(fIntervals[0]));
+    buffer.writeBool(fScaleToFit);
+    buffer.writeScalarArray(fIntervals, fCount);
 }
 
 SkFlattenable* SkDashPathEffect::CreateProc(SkFlattenableReadBuffer& buffer) {
     return SkNEW_ARGS(SkDashPathEffect, (buffer));
 }
 
-SkDashPathEffect::SkDashPathEffect(SkFlattenableReadBuffer& buffer) {
-    fCount = buffer.readS32();
-    fInitialDashIndex = buffer.readS32();
+SkDashPathEffect::SkDashPathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
+    fInitialDashIndex = buffer.readInt();
     fInitialDashLength = buffer.readScalar();
     fIntervalLength = buffer.readScalar();
-    fScaleToFit = (buffer.readS32() != 0);
+    fScaleToFit = buffer.readBool();
     
+    fCount = buffer.getArrayCount();
     fIntervals = (SkScalar*)sk_malloc_throw(sizeof(SkScalar) * fCount);
-    buffer.read(fIntervals, fCount * sizeof(fIntervals[0]));
+    buffer.readScalarArray(fIntervals);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/src/effects/SkDiscretePathEffect.cpp b/src/effects/SkDiscretePathEffect.cpp
index 0536e56..77a6ec6 100644
--- a/src/effects/SkDiscretePathEffect.cpp
+++ b/src/effects/SkDiscretePathEffect.cpp
@@ -9,6 +9,7 @@
 
 #include "SkDiscretePathEffect.h"
 #include "SkBuffer.h"
+#include "SkFlattenableBuffers.h"
 #include "SkPathMeasure.h"
 #include "SkRandom.h"
 
diff --git a/src/effects/SkEmbossMaskFilter.cpp b/src/effects/SkEmbossMaskFilter.cpp
index 9ecba34..ebc3add 100644
--- a/src/effects/SkEmbossMaskFilter.cpp
+++ b/src/effects/SkEmbossMaskFilter.cpp
@@ -12,6 +12,7 @@
 #include "SkBlurMask.h"
 #include "SkEmbossMask.h"
 #include "SkBuffer.h"
+#include "SkFlattenableBuffers.h"
 
 static inline int pin2byte(int n) {
     if (n < 0) {
@@ -117,7 +118,8 @@
 
 SkEmbossMaskFilter::SkEmbossMaskFilter(SkFlattenableReadBuffer& buffer)
         : SkMaskFilter(buffer) {
-    buffer.read(&fLight, sizeof(fLight));
+    SkASSERT(buffer.getArrayCount() == sizeof(Light));
+    buffer.readByteArray(&fLight);
     SkASSERT(fLight.fPad == 0); // for the font-cache lookup to be clean
     fBlurRadius = buffer.readScalar();
 }
@@ -127,7 +129,7 @@
 
     Light tmpLight = fLight;
     tmpLight.fPad = 0;    // for the font-cache lookup to be clean
-    buffer.writeMul4(&tmpLight, sizeof(tmpLight));
+    buffer.writeByteArray(&tmpLight, sizeof(tmpLight));
     buffer.writeScalar(fBlurRadius);
 }
 
diff --git a/src/effects/SkGroupShape.cpp b/src/effects/SkGroupShape.cpp
index 0468d5b..224d2a2 100644
--- a/src/effects/SkGroupShape.cpp
+++ b/src/effects/SkGroupShape.cpp
@@ -6,6 +6,7 @@
  * found in the LICENSE file.
  */
 #include "SkGroupShape.h"
+#include "SkFlattenableBuffers.h"
 
 SkGroupShape::SkGroupShape() {}
 
@@ -86,8 +87,7 @@
 void SkGroupShape::flatten(SkFlattenableWriteBuffer& buffer) const {
     this->INHERITED::flatten(buffer);
 
-    int count = fList.count();
-    buffer.write32(count);
+    buffer.writeInt(fList.count());
     const Rec* rec = fList.begin();
     const Rec* stop = fList.end();
     while (rec < stop) {
@@ -101,9 +101,9 @@
 }
 
 SkGroupShape::SkGroupShape(SkFlattenableReadBuffer& buffer) : INHERITED(buffer){
-    int count = buffer.readS32();
+    int count = buffer.readInt();
     for (int i = 0; i < count; i++) {
-        SkShape* shape = reinterpret_cast<SkShape*>(buffer.readFlattenable());
+        SkShape* shape = buffer.readFlattenableT<SkShape>();
         SkMatrixRef* mr = NULL;
         bool hasMatrix = buffer.readBool();
         if (hasMatrix) {
diff --git a/src/effects/SkKernel33MaskFilter.cpp b/src/effects/SkKernel33MaskFilter.cpp
index 10aabc4..9426dd9 100644
--- a/src/effects/SkKernel33MaskFilter.cpp
+++ b/src/effects/SkKernel33MaskFilter.cpp
@@ -7,6 +7,7 @@
  */
 #include "SkKernel33MaskFilter.h"
 #include "SkColorPriv.h"
+#include "SkFlattenableBuffers.h"
 
 SkMask::Format SkKernel33ProcMaskFilter::getFormat() {
     return SkMask::kA8_Format;
@@ -75,12 +76,12 @@
 
 void SkKernel33ProcMaskFilter::flatten(SkFlattenableWriteBuffer& wb) const {
     this->INHERITED::flatten(wb);
-    wb.write32(fPercent256);
+    wb.writeInt(fPercent256);
 }
 
 SkKernel33ProcMaskFilter::SkKernel33ProcMaskFilter(SkFlattenableReadBuffer& rb)
         : SkMaskFilter(rb) {
-    fPercent256 = rb.readS32();
+    fPercent256 = rb.readInt();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -106,13 +107,14 @@
 
 void SkKernel33MaskFilter::flatten(SkFlattenableWriteBuffer& wb) const {
     this->INHERITED::flatten(wb);
-    wb.writeMul4(fKernel, 9 * sizeof(int));
-    wb.write32(fShift);
+    wb.writeIntArray(&fKernel[0][0], 9);
+    wb.writeInt(fShift);
 }
 
 SkKernel33MaskFilter::SkKernel33MaskFilter(SkFlattenableReadBuffer& rb)
         : SkKernel33ProcMaskFilter(rb) {
-    rb.read(fKernel, 9 * sizeof(int));
-    fShift = rb.readS32();
+    const uint32_t count = rb.readIntArray(&fKernel[0][0]);
+    SkASSERT(9 == count);
+    fShift = rb.readInt();
 }
 
diff --git a/src/effects/SkLayerDrawLooper.cpp b/src/effects/SkLayerDrawLooper.cpp
index c8da568..a32cf9b 100644
--- a/src/effects/SkLayerDrawLooper.cpp
+++ b/src/effects/SkLayerDrawLooper.cpp
@@ -7,6 +7,7 @@
  */
 #include "SkCanvas.h"
 #include "SkColor.h"
+#include "SkFlattenableBuffers.h"
 #include "SkLayerDrawLooper.h"
 #include "SkPaint.h"
 #include "SkUnPreMultiply.h"
@@ -204,10 +205,9 @@
         buffer.writeInt(rec->fInfo.fFlagsMask);
         buffer.writeInt(rec->fInfo.fPaintBits);
         buffer.writeInt(rec->fInfo.fColorMode);
-        buffer.writeScalar(rec->fInfo.fOffset.fX);
-        buffer.writeScalar(rec->fInfo.fOffset.fY);
+        buffer.writePoint(rec->fInfo.fOffset);
         buffer.writeBool(rec->fInfo.fPostTranslate);
-        rec->fPaint.flatten(buffer);
+        buffer.writePaint(rec->fPaint);
         rec = rec->fNext;
     }
 }
@@ -224,10 +224,9 @@
         info.fFlagsMask = buffer.readInt();
         info.fPaintBits = buffer.readInt();
         info.fColorMode = (SkXfermode::Mode)buffer.readInt();
-        info.fOffset.fX = buffer.readScalar();
-        info.fOffset.fY = buffer.readScalar();
+        buffer.readPoint(&info.fOffset);
         info.fPostTranslate = buffer.readBool();
-        this->addLayer(info)->unflatten(buffer);
+        buffer.readPaint(this->addLayer(info));
     }
     SkASSERT(count == fCount);
 
diff --git a/src/effects/SkLayerRasterizer.cpp b/src/effects/SkLayerRasterizer.cpp
index dbcbefd..8aaa9fb 100644
--- a/src/effects/SkLayerRasterizer.cpp
+++ b/src/effects/SkLayerRasterizer.cpp
@@ -10,6 +10,7 @@
 #include "SkLayerRasterizer.h"
 #include "SkBuffer.h"
 #include "SkDraw.h"
+#include "SkFlattenableBuffers.h"
 #include "SkMask.h"
 #include "SkMaskFilter.h"
 #include "SkPaint.h"
@@ -143,78 +144,30 @@
     return true;
 }
 
-/////////// Routines for flattening /////////////////
-
-static void paint_read(SkPaint* paint, SkFlattenableReadBuffer& buffer) {
-    paint->setAntiAlias(buffer.readBool());
-    paint->setStyle((SkPaint::Style)buffer.readU8());
-    paint->setAlpha(buffer.readU8());
-
-    if (paint->getStyle() != SkPaint::kFill_Style) {
-        paint->setStrokeWidth(buffer.readScalar());
-        paint->setStrokeMiter(buffer.readScalar());
-        paint->setStrokeCap((SkPaint::Cap)buffer.readU8());
-        paint->setStrokeJoin((SkPaint::Join)buffer.readU8());
-    }
-
-    SkSafeUnref(paint->setMaskFilter((SkMaskFilter*)buffer.readFlattenable()));
-    SkSafeUnref(paint->setPathEffect((SkPathEffect*)buffer.readFlattenable()));
-    SkSafeUnref(paint->setRasterizer((SkRasterizer*)buffer.readFlattenable()));
-    SkSafeUnref(paint->setXfermode((SkXfermode*)buffer.readFlattenable()));
-}
-
-static void paint_write(const SkPaint& paint, SkFlattenableWriteBuffer& buffer) {
-    buffer.writeBool(paint.isAntiAlias());
-    buffer.write8(paint.getStyle());
-    buffer.write8(paint.getAlpha());
-
-    if (paint.getStyle() != SkPaint::kFill_Style) {
-        buffer.writeScalar(paint.getStrokeWidth());
-        buffer.writeScalar(paint.getStrokeMiter());
-        buffer.write8(paint.getStrokeCap());
-        buffer.write8(paint.getStrokeJoin());
-    }
-
-    buffer.writeFlattenable(paint.getMaskFilter());
-    buffer.writeFlattenable(paint.getPathEffect());
-    buffer.writeFlattenable(paint.getRasterizer());
-    buffer.writeFlattenable(paint.getXfermode());
-}
-
 SkLayerRasterizer::SkLayerRasterizer(SkFlattenableReadBuffer& buffer)
     : SkRasterizer(buffer), fLayers(sizeof(SkLayerRasterizer_Rec)) {
-    int count = buffer.readS32();
+    int count = buffer.readInt();
 
     for (int i = 0; i < count; i++) {
         SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers.push_back();
 
-#if 0
-        SkNEW_PLACEMENT_ARGS(&rec->fPaint, SkPaint, (buffer));
-#else
         SkNEW_PLACEMENT(&rec->fPaint, SkPaint);
-        paint_read(&rec->fPaint, buffer);
-#endif
-        rec->fOffset.fX = buffer.readScalar();
-        rec->fOffset.fY = buffer.readScalar();
+        buffer.readPaint(&rec->fPaint);
+        buffer.readPoint(&rec->fOffset);
     }
 }
 
 void SkLayerRasterizer::flatten(SkFlattenableWriteBuffer& buffer) const {
     this->INHERITED::flatten(buffer);
 
-    buffer.write32(fLayers.count());
+    buffer.writeInt(fLayers.count());
 
     SkDeque::F2BIter                iter(fLayers);
     const SkLayerRasterizer_Rec*    rec;
 
     while ((rec = (const SkLayerRasterizer_Rec*)iter.next()) != NULL) {
-#if 0
-        rec->fPaint.flatten(buffer);
-#else
-        paint_write(rec->fPaint, buffer);
-#endif
-        buffer.writeScalar(rec->fOffset.fX);
-        buffer.writeScalar(rec->fOffset.fY);
+        buffer.writePaint(rec->fPaint);
+        buffer.writePoint(rec->fOffset);
     }
 }
 
diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp
index b6532aa..c590c26 100644
--- a/src/effects/SkLightingImageFilter.cpp
+++ b/src/effects/SkLightingImageFilter.cpp
@@ -8,6 +8,9 @@
 #include "SkLightingImageFilter.h"
 #include "SkBitmap.h"
 #include "SkColorPriv.h"
+#include "SkFlattenableBuffers.h"
+#include "SkOrderedReadBuffer.h"
+#include "SkOrderedWriteBuffer.h"
 #include "SkTypes.h"
 
 #if SK_SUPPORT_GPU
@@ -754,7 +757,7 @@
 SkLightingImageFilter::SkLightingImageFilter(SkFlattenableReadBuffer& buffer)
   : INHERITED(buffer)
 {
-    fLight = (SkLight*)buffer.readFlattenable();
+    fLight = buffer.readFlattenableT<SkLight>();
     fSurfaceScale = buffer.readScalar();
 }
 
diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp
index b0fc289..c1e2d26 100644
--- a/src/effects/SkMorphologyImageFilter.cpp
+++ b/src/effects/SkMorphologyImageFilter.cpp
@@ -8,6 +8,8 @@
 #include "SkMorphologyImageFilter.h"
 #include "SkBitmap.h"
 #include "SkColorPriv.h"
+#include "SkFlattenableBuffers.h"
+#include "SkRect.h"
 #if SK_SUPPORT_GPU
 #include "GrContext.h"
 #include "GrTexture.h"
diff --git a/src/effects/SkPixelXorXfermode.cpp b/src/effects/SkPixelXorXfermode.cpp
index 7b58ed7..236aec5 100644
--- a/src/effects/SkPixelXorXfermode.cpp
+++ b/src/effects/SkPixelXorXfermode.cpp
@@ -9,6 +9,7 @@
 
 #include "SkPixelXorXfermode.h"
 #include "SkColorPriv.h"
+#include "SkFlattenableBuffers.h"
 
 // we always return an opaque color, 'cause I don't know what to do with
 // the alpha-component and still return a valid premultiplied color.
@@ -20,12 +21,12 @@
 
 void SkPixelXorXfermode::flatten(SkFlattenableWriteBuffer& wb) const {
     this->INHERITED::flatten(wb);
-    wb.write32(fOpColor);
+    wb.writeColor(fOpColor);
 }
 
 SkPixelXorXfermode::SkPixelXorXfermode(SkFlattenableReadBuffer& rb)
         : INHERITED(rb) {
-    fOpColor = rb.readU32();
+    fOpColor = rb.readColor();
 }
 
 SK_DEFINE_FLATTENABLE_REGISTRAR(SkPixelXorXfermode)
diff --git a/src/effects/SkRectShape.cpp b/src/effects/SkRectShape.cpp
index 68d1e1f..0663106 100644
--- a/src/effects/SkRectShape.cpp
+++ b/src/effects/SkRectShape.cpp
@@ -9,6 +9,7 @@
 
 #include "SkRectShape.h"
 #include "SkCanvas.h"
+#include "SkFlattenableBuffers.h"
 
 SkPaintShape::SkPaintShape() {
     fPaint.setAntiAlias(true);
@@ -64,24 +65,25 @@
     this->INHERITED::flatten(buffer);
 
     buffer.writeRect(fBounds);
-    *(SkSize*)buffer.reserve(sizeof(SkSize)) = fRadii;
+    buffer.writeScalar(fRadii.fWidth);
+    buffer.writeScalar(fRadii.fHeight);
 }
 
-SkRectShape::SkRectShape(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {    
-    buffer.read(&fBounds, sizeof(fBounds));
-    buffer.read(&fRadii, sizeof(fRadii));
+SkRectShape::SkRectShape(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
+    buffer.readRect(&fBounds);
+    fRadii.fWidth = buffer.readScalar();
+    fRadii.fHeight = buffer.readScalar();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
 void SkPaintShape::flatten(SkFlattenableWriteBuffer& buffer) const {
     this->INHERITED::flatten(buffer);
-    
-    fPaint.flatten(buffer);
+    buffer.writePaint(fPaint);
 }
 
 SkPaintShape::SkPaintShape(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
-    fPaint.unflatten(buffer);
+    buffer.readPaint(&fPaint);
 }
 
 SK_DEFINE_FLATTENABLE_REGISTRAR(SkRectShape)
diff --git a/src/effects/SkTableColorFilter.cpp b/src/effects/SkTableColorFilter.cpp
index 769a40d..f316c52 100644
--- a/src/effects/SkTableColorFilter.cpp
+++ b/src/effects/SkTableColorFilter.cpp
@@ -1,6 +1,8 @@
+
 #include "SkBitmap.h"
-#include "SkColorPriv.h"
 #include "SkTableColorFilter.h"
+#include "SkColorPriv.h"
+#include "SkFlattenableBuffers.h"
 #include "SkUnPreMultiply.h"
 
 class SkTable_ColorFilter : public SkColorFilter {
@@ -161,8 +163,7 @@
 //    SkDebugf("raw %d packed %d\n", count * 256, size);
     
     buffer.writeInt(fFlags);
-    buffer.writeInt(size);
-    buffer.write(storage, size);
+    buffer.writeByteArray(storage, size);
 }
 
 SkTable_ColorFilter::SkTable_ColorFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
@@ -171,8 +172,10 @@
     uint8_t storage[5*256];
 
     fFlags = buffer.readInt();
-    size_t size = buffer.readInt();
-    buffer.read(storage, size);
+
+    size_t size = buffer.getArrayCount();
+    SkASSERT(size <= sizeof(storage));
+    buffer.readByteArray(storage);
 
     size_t raw = SkPackBits::Unpack8(storage, size, fStorage);
 
diff --git a/src/effects/SkTableMaskFilter.cpp b/src/effects/SkTableMaskFilter.cpp
index 43da55e..495affb 100644
--- a/src/effects/SkTableMaskFilter.cpp
+++ b/src/effects/SkTableMaskFilter.cpp
@@ -8,6 +8,7 @@
 
 
 #include "SkTableMaskFilter.h"
+#include "SkFlattenableBuffers.h"
 
 SkTableMaskFilter::SkTableMaskFilter() {
     for (int i = 0; i < 256; i++) {
@@ -73,12 +74,13 @@
 
 void SkTableMaskFilter::flatten(SkFlattenableWriteBuffer& wb) const {
     this->INHERITED::flatten(wb);
-    wb.writePad(fTable, 256);
+    wb.writeByteArray(fTable, 256);
 }
 
 SkTableMaskFilter::SkTableMaskFilter(SkFlattenableReadBuffer& rb)
         : INHERITED(rb) {
-    rb.read(fTable, 256);
+    SkASSERT(256 == rb.getArrayCount());
+    rb.readByteArray(fTable);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/src/effects/SkTestImageFilters.cpp b/src/effects/SkTestImageFilters.cpp
index 2633b09..70e39ef 100755
--- a/src/effects/SkTestImageFilters.cpp
+++ b/src/effects/SkTestImageFilters.cpp
@@ -1,6 +1,8 @@
+
 #include "SkTestImageFilters.h"
 #include "SkCanvas.h"
 #include "SkDevice.h"
+#include "SkFlattenableBuffers.h"
 
 // Simple helper canvas that "takes ownership" of the provided device, so that
 // when this canvas goes out of scope, so will its device. Could be replaced
@@ -41,13 +43,11 @@
 
 void SkOffsetImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
     this->INHERITED::flatten(buffer);
-    buffer.writeScalar(fOffset.x());
-    buffer.writeScalar(fOffset.y());
+    buffer.writePoint(fOffset);
 }
 
 SkOffsetImageFilter::SkOffsetImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
-    fOffset.fX = buffer.readScalar();
-    fOffset.fY = buffer.readScalar();
+    buffer.readPoint(&fOffset);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -99,8 +99,8 @@
 }
 
 SkComposeImageFilter::SkComposeImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
-    fOuter = (SkImageFilter*)buffer.readFlattenable();
-    fInner = (SkImageFilter*)buffer.readFlattenable();
+    fOuter = buffer.readFlattenableT<SkImageFilter>();
+    fInner = buffer.readFlattenableT<SkImageFilter>();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -253,29 +253,30 @@
         // negative count signals we have modes
         storedCount = -storedCount;
     }
-    buffer.write32(storedCount);
+    buffer.writeInt(storedCount);
 
     if (fCount) {
         for (int i = 0; i < fCount; ++i) {
             buffer.writeFlattenable(fFilters[i]);
         }
         if (fModes) {
-            buffer.write(fModes, fCount * sizeof(fModes[0]));
+            buffer.writeByteArray(fModes, fCount * sizeof(fModes[0]));
         }
     }
 }
 
 SkMergeImageFilter::SkMergeImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
-    int storedCount = buffer.readS32();
+    int storedCount = buffer.readInt();
     this->initAlloc(SkAbs32(storedCount), storedCount < 0);
 
     for (int i = 0; i < fCount; ++i) {
-        fFilters[i] = (SkImageFilter*)buffer.readFlattenable();
+        fFilters[i] = buffer.readFlattenableT<SkImageFilter>();
     }
 
     if (fModes) {
         SkASSERT(storedCount < 0);
-        buffer.read(fModes, fCount * sizeof(fModes[0]));
+        SkASSERT(buffer.getArrayCount() == fCount * sizeof(fModes[0]));
+        buffer.readByteArray(fModes);
     } else {
         SkASSERT(storedCount >= 0);
     }
@@ -321,7 +322,7 @@
 }
 
 SkColorFilterImageFilter::SkColorFilterImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
-    fColorFilter = (SkColorFilter*)buffer.readFlattenable();
+    fColorFilter = buffer.readFlattenableT<SkColorFilter>();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp
index f61f8d5..a07b388 100644
--- a/src/effects/gradients/SkGradientShader.cpp
+++ b/src/effects/gradients/SkGradientShader.cpp
@@ -134,30 +134,30 @@
     INHERITED(buffer) {
     fCacheAlpha = 256;
 
-    fMapper = static_cast<SkUnitMapper*>(buffer.readFlattenable());
+    fMapper = buffer.readFlattenableT<SkUnitMapper>();
 
     fCache16 = fCache16Storage = NULL;
     fCache32 = NULL;
     fCache32PixelRef = NULL;
 
-    int colorCount = fColorCount = buffer.readU32();
+    int colorCount = fColorCount = buffer.getArrayCount();
     if (colorCount > kColorStorageCount) {
         size_t size = sizeof(SkColor) + sizeof(SkPMColor) + sizeof(Rec);
         fOrigColors = (SkColor*)sk_malloc_throw(size * colorCount);
     } else {
         fOrigColors = fStorage;
     }
-    buffer.read(fOrigColors, colorCount * sizeof(SkColor));
+    buffer.readColorArray(fOrigColors);
 
-    fTileMode = (TileMode)buffer.readU8();
+    fTileMode = (TileMode)buffer.readUInt();
     fTileProc = gTileProcs[fTileMode];
     fRecs = (Rec*)(fOrigColors + colorCount);
     if (colorCount > 2) {
         Rec* recs = fRecs;
         recs[0].fPos = 0;
         for (int i = 1; i < colorCount; i++) {
-            recs[i].fPos = buffer.readS32();
-            recs[i].fScale = buffer.readU32();
+            recs[i].fPos = buffer.readInt();
+            recs[i].fScale = buffer.readUInt();
         }
     }
     buffer.readMatrix(&fPtsToUnit);
@@ -187,14 +187,13 @@
 void SkGradientShaderBase::flatten(SkFlattenableWriteBuffer& buffer) const {
     this->INHERITED::flatten(buffer);
     buffer.writeFlattenable(fMapper);
-    buffer.write32(fColorCount);
-    buffer.writeMul4(fOrigColors, fColorCount * sizeof(SkColor));
-    buffer.write8(fTileMode);
+    buffer.writeColorArray(fOrigColors, fColorCount);
+    buffer.writeUInt(fTileMode);
     if (fColorCount > 2) {
         Rec* recs = fRecs;
         for (int i = 1; i < fColorCount; i++) {
-            buffer.write32(recs[i].fPos);
-            buffer.write32(recs[i].fScale);
+            buffer.writeInt(recs[i].fPos);
+            buffer.writeUInt(recs[i].fScale);
         }
     }
     buffer.writeMatrix(fPtsToUnit);
diff --git a/src/effects/gradients/SkGradientShaderPriv.h b/src/effects/gradients/SkGradientShaderPriv.h
index 807bf32..8152d5f 100644
--- a/src/effects/gradients/SkGradientShaderPriv.h
+++ b/src/effects/gradients/SkGradientShaderPriv.h
@@ -12,6 +12,7 @@
 #include "SkGradientShader.h"
 #include "SkClampRange.h"
 #include "SkColorPriv.h"
+#include "SkFlattenableBuffers.h"
 #include "SkMallocPixelRef.h"
 #include "SkUnitMapper.h"
 #include "SkUtils.h"
diff --git a/src/images/SkFlipPixelRef.cpp b/src/images/SkFlipPixelRef.cpp
index 6ab5bbc..4e42d6c 100644
--- a/src/images/SkFlipPixelRef.cpp
+++ b/src/images/SkFlipPixelRef.cpp
@@ -6,7 +6,7 @@
  * found in the LICENSE file.
  */
 #include "SkFlipPixelRef.h"
-#include "SkFlattenable.h"
+#include "SkFlattenableBuffers.h"
 #include "SkRegion.h"
 
 SkFlipPixelRef::SkFlipPixelRef(SkBitmap::Config config, int width, int height)
@@ -62,19 +62,17 @@
 
 void SkFlipPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
     this->INHERITED::flatten(buffer);
-    
-    buffer.write32(fSize);
     // only need to write page0
-    buffer.writePad(fPage0, fSize);
+    buffer.writeByteArray(fPage0, fSize);
 }
 
 SkFlipPixelRef::SkFlipPixelRef(SkFlattenableReadBuffer& buffer)
         : INHERITED(buffer, NULL) {
-    fSize = buffer.readU32();
+    fSize = buffer.getArrayCount();
     fStorage = sk_malloc_throw(fSize << 1);
     fPage0 = fStorage;
     fPage1 = (char*)fStorage + fSize;
-    buffer.read(fPage0, fSize);
+    buffer.readByteArray(fPage0);
 }
 
 SK_DEFINE_FLATTENABLE_REGISTRAR(SkFlipPixelRef)
diff --git a/src/images/SkImageRef.cpp b/src/images/SkImageRef.cpp
index 1d6b270..39a1de9 100644
--- a/src/images/SkImageRef.cpp
+++ b/src/images/SkImageRef.cpp
@@ -7,7 +7,7 @@
  */
 #include "SkImageRef.h"
 #include "SkBitmap.h"
-#include "SkFlattenable.h"
+#include "SkFlattenableBuffers.h"
 #include "SkImageDecoder.h"
 #include "SkStream.h"
 #include "SkTemplates.h"
@@ -177,13 +177,13 @@
 
 SkImageRef::SkImageRef(SkFlattenableReadBuffer& buffer)
         : INHERITED(buffer, &gImageRefMutex), fErrorInDecoding(false) {
-    fConfig = (SkBitmap::Config)buffer.readU8();
-    fSampleSize = buffer.readU8();
+    fConfig = (SkBitmap::Config)buffer.readUInt();
+    fSampleSize = buffer.readInt();
     fDoDither = buffer.readBool();
 
-    size_t length = buffer.readU32();
+    size_t length = buffer.getArrayCount();
     fStream = SkNEW_ARGS(SkMemoryStream, (length));
-    buffer.read((void*)fStream->getMemoryBase(), length);
+    buffer.readByteArray((void*)fStream->getMemoryBase());
 
     fPrev = fNext = NULL;
     fFactory = NULL;
@@ -192,12 +192,10 @@
 void SkImageRef::flatten(SkFlattenableWriteBuffer& buffer) const {
     this->INHERITED::flatten(buffer);
 
-    buffer.write8(fConfig);
-    buffer.write8(fSampleSize);
+    buffer.writeUInt(fConfig);
+    buffer.writeInt(fSampleSize);
     buffer.writeBool(fDoDither);
-    size_t length = fStream->getLength();
-    buffer.write32(length);
     fStream->rewind();
-    buffer.readFromStream(fStream, length);
+    buffer.writeStream(fStream, fStream->getLength());
 }
 
diff --git a/src/pdf/SkPDFUtils.h b/src/pdf/SkPDFUtils.h
index 1bce614..1bdbf78 100644
--- a/src/pdf/SkPDFUtils.h
+++ b/src/pdf/SkPDFUtils.h
@@ -17,6 +17,7 @@
 class SkPath;
 class SkPDFArray;
 struct SkRect;
+class SkWStream;
 
 #if 0
 #define PRINT_NOT_IMPL(str) fprintf(stderr, str)
diff --git a/src/pipe/SkGPipeRead.cpp b/src/pipe/SkGPipeRead.cpp
index a8cba27..725a57b 100644
--- a/src/pipe/SkGPipeRead.cpp
+++ b/src/pipe/SkGPipeRead.cpp
@@ -78,7 +78,7 @@
         return fFlags;
     }
 
-    void setReader(SkFlattenableReadBuffer* reader) {
+    void setReader(SkOrderedReadBuffer* reader) {
         fReader = reader;
         this->updateReader();
     }
@@ -129,7 +129,7 @@
     }
 
     void addTypeface() {
-        size_t size = fReader->readU32();
+        size_t size = fReader->read32();
         const void* data = fReader->skip(SkAlign4(size));
         SkMemoryStream stream(data, size, false);
         *fTypefaces.append() = SkTypeface::Deserialize(&stream);
@@ -152,7 +152,7 @@
             fReader->setFactoryArray(NULL);
         }
     }
-    SkFlattenableReadBuffer*  fReader;
+    SkOrderedReadBuffer*      fReader;
     SkPaint                   fPaint;
     SkTDArray<SkFlattenable*> fFlatArray;
     SkTDArray<SkTypeface*>    fTypefaces;
@@ -677,7 +677,7 @@
 
     fState->setReader(&reader);
     while (!reader.eof()) {
-        uint32_t op32 = reader.readU32();
+        uint32_t op32 = reader.readUInt();
         unsigned op = DrawOp_unpackOp(op32);
         // SkDEBUGCODE(DrawOps drawOp = (DrawOps)op;)
         
diff --git a/src/ports/SkImageRef_ashmem.cpp b/src/ports/SkImageRef_ashmem.cpp
index 6ea5c95..81f24dd 100644
--- a/src/ports/SkImageRef_ashmem.cpp
+++ b/src/ports/SkImageRef_ashmem.cpp
@@ -214,14 +214,7 @@
 
 void SkImageRef_ashmem::flatten(SkFlattenableWriteBuffer& buffer) const {
     this->INHERITED::flatten(buffer);
-    const char* uri = getURI();
-    if (uri) {
-        size_t len = strlen(uri);
-        buffer.write32(len);
-        buffer.writePad(uri, len);
-    } else {
-        buffer.write32(0);
-    }
+    buffer.writeString(getURI());
 }
 
 SkImageRef_ashmem::SkImageRef_ashmem(SkFlattenableReadBuffer& buffer)
@@ -231,17 +224,12 @@
     fRec.fSize = 0;
     fRec.fPinned = false;
     fCT = NULL;
-    size_t length = buffer.readU32();
-    if (length) {
-        char* buf = (char*) malloc(length);
-        buffer.read(buf, length);
-        setURI(buf, length);
+    const char* uri = buffer.readString();
+    if (uri) {
+        setURI(uri);
+        sk_free(uri);
     }
     this->useDefaultMutex();   // we don't need/want the shared imageref mutex
 }
 
-SkPixelRef* SkImageRef_ashmem::Create(SkFlattenableReadBuffer& buffer) {
-    return SkNEW_ARGS(SkImageRef_ashmem, (buffer));
-}
-
 SK_DEFINE_FLATTENABLE_REGISTRAR(SkImageRef_ashmem)
diff --git a/src/utils/SkUnitMappers.cpp b/src/utils/SkUnitMappers.cpp
index b2ab02b..735a434 100644
--- a/src/utils/SkUnitMappers.cpp
+++ b/src/utils/SkUnitMappers.cpp
@@ -6,6 +6,7 @@
  * found in the LICENSE file.
  */
 #include "SkUnitMappers.h"
+#include "SkFlattenableBuffers.h"
 
 SK_DEFINE_INST_COUNT(SkUnitMapper)
 
@@ -31,14 +32,14 @@
 
 SkDiscreteMapper::SkDiscreteMapper(SkFlattenableReadBuffer& rb)
         : SkUnitMapper(rb) {
-    fSegments = rb.readU32();
-    fScale = rb.readU32();
+    fSegments = rb.readInt();
+    fScale = rb.read32();
 }
 
 void SkDiscreteMapper::flatten(SkFlattenableWriteBuffer& wb) const {
     this->INHERITED::flatten(wb);
 
-    wb.write32(fSegments);
+    wb.writeInt(fSegments);
     wb.write32(fScale);
 }