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/gyp/core.gyp b/gyp/core.gyp
index 376512b..6af2a57 100644
--- a/gyp/core.gyp
+++ b/gyp/core.gyp
@@ -72,6 +72,7 @@
         '../src/core/SkFilterProc.cpp',
         '../src/core/SkFilterProc.h',
         '../src/core/SkFlattenable.cpp',
+        '../src/core/SkFlattenableBuffers.cpp',
         '../src/core/SkFloat.cpp',
         '../src/core/SkFloat.h',
         '../src/core/SkFloatBits.cpp',
diff --git a/include/core/SkAnnotation.h b/include/core/SkAnnotation.h
index d401588..9cdb2d5 100644
--- a/include/core/SkAnnotation.h
+++ b/include/core/SkAnnotation.h
@@ -12,6 +12,8 @@
 
 class SkData;
 class SkDataSet;
+class SkStream;
+class SkWStream;
 
 /**
  *  Experimental class for annotating draws. Do not use directly yet.
diff --git a/include/core/SkBitmap.h b/include/core/SkBitmap.h
index 9ddd702..b4f86ea 100644
--- a/include/core/SkBitmap.h
+++ b/include/core/SkBitmap.h
@@ -21,8 +21,6 @@
 class SkPaint;
 class SkPixelRef;
 class SkRegion;
-class SkFlattenableReadBuffer;
-class SkFlattenableWriteBuffer;
 
 // This is an opaque class, not interpreted by skia
 class SkGpuTexture;
diff --git a/include/core/SkColorFilter.h b/include/core/SkColorFilter.h
index 76a0c93..4c5eee7 100644
--- a/include/core/SkColorFilter.h
+++ b/include/core/SkColorFilter.h
@@ -14,6 +14,8 @@
 #include "SkFlattenable.h"
 #include "SkXfermode.h"
 
+class SkBitmap;
+
 class SK_API SkColorFilter : public SkFlattenable {
 public:
     SK_DECLARE_INST_COUNT(SkColorFilter)
diff --git a/include/core/SkDrawLooper.h b/include/core/SkDrawLooper.h
index 0e99651..f1fb5bd 100644
--- a/include/core/SkDrawLooper.h
+++ b/include/core/SkDrawLooper.h
@@ -14,6 +14,7 @@
 
 class SkCanvas;
 class SkPaint;
+struct SkRect;
 
 /** \class SkDrawLooper
     Subclasses of SkDrawLooper can be attached to a SkPaint. Where they are,
diff --git a/include/core/SkFlattenable.h b/include/core/SkFlattenable.h
index bbd4a80..56bc966 100644
--- a/include/core/SkFlattenable.h
+++ b/include/core/SkFlattenable.h
@@ -11,16 +11,9 @@
 #define SkFlattenable_DEFINED
 
 #include "SkRefCnt.h"
-#include "SkReader32.h"
-#include "SkTDArray.h"
-#include "SkWriter32.h"
 
-class SkBitmap;
 class SkFlattenableReadBuffer;
 class SkFlattenableWriteBuffer;
-class SkPath;
-struct SkPoint;
-class SkString;
 
 #if SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
 
@@ -55,7 +48,7 @@
     virtual Factory getFactory() SK_OVERRIDE { return NULL; }; \
 
 #define SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(flattenable) \
-    virtual Factory getFactory() SK_OVERRIDE { return CreateProc; }; \
+    virtual Factory getFactory() SK_OVERRIDE { return CreateProc; } \
     static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { \
         return SkNEW_ARGS(flattenable, (buffer)); \
     }
@@ -110,116 +103,6 @@
     typedef SkRefCnt INHERITED;
 };
 
-// helpers for matrix and region
-
-class SkMatrix;
-extern void SkReadMatrix(SkReader32*, SkMatrix*);
-extern void SkWriteMatrix(SkWriter32*, const SkMatrix&);
-
-class SkRegion;
-extern void SkReadRegion(SkReader32*, SkRegion*);
-extern void SkWriteRegion(SkWriter32*, const SkRegion&);
-
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-class SkTypeface;
-
-class SkFlattenableReadBuffer {
-public:
-    enum Flags {
-        kCrossProcess_Flag      = 1 << 0,
-        kScalarIsFloat_Flag     = 1 << 1,
-        kPtrIs64Bit_Flag        = 1 << 2,
-    };
-
-    SkFlattenableReadBuffer();
-    virtual ~SkFlattenableReadBuffer() {}
-
-    void setFlags(uint32_t flags) { fFlags = flags; }
-    uint32_t getFlags() const { return fFlags; }
-
-    bool isCrossProcess() const { return SkToBool(fFlags & kCrossProcess_Flag); }
-    bool isScalarFloat() const { return SkToBool(fFlags & kScalarIsFloat_Flag); }
-    bool isPtr64Bit() const { return SkToBool(fFlags & kPtrIs64Bit_Flag); }
-
-    virtual uint8_t readU8() = 0;
-    virtual uint16_t readU16() = 0;
-    virtual uint32_t readU32() = 0;
-    virtual void read(void* dst, size_t size) = 0;
-    virtual bool readBool() = 0;
-    virtual int32_t readInt() = 0;
-    virtual SkScalar readScalar() = 0;
-    virtual const void* skip(size_t size) = 0;
-
-    virtual int32_t readS32() { return readInt(); }
-    template <typename T> const T& skipT() {
-        SkASSERT(SkAlign4(sizeof(T)) == sizeof(T));
-        return *(const T*)this->skip(sizeof(T));
-    }
-
-    virtual void readMatrix(SkMatrix*) = 0;
-    virtual void readPath(SkPath*) = 0;
-    virtual void readPoint(SkPoint*) = 0;
-
-    // helper function for classes with const SkPoint members
-    SkPoint readPoint() {
-        SkPoint point;
-        this->readPoint(&point);
-        return point;
-    }
-
-    void setRefCntArray(SkRefCnt* array[], int count) {
-        fRCArray = array;
-        fRCCount = count;
-    }
-    
-    void setTypefaceArray(SkTypeface* array[], int count) {
-        fTFArray = array;
-        fTFCount = count;
-    }
-
-    /**
-     *  Call this with a pre-loaded array of Factories, in the same order as
-     *  were created/written by the writer. SkPicture uses this.
-     */
-    void setFactoryPlayback(SkFlattenable::Factory array[], int count) {
-        fFactoryTDArray = NULL;
-        fFactoryArray = array;
-        fFactoryCount = count;
-    }
-
-    /**
-     *  Call this with an initially empty array, so the reader can cache each
-     *  factory it sees by name. Used by the pipe code in combination with
-     *  setNamedFactoryRecorder.
-     */
-    void setFactoryArray(SkTDArray<SkFlattenable::Factory>* array) {
-        fFactoryTDArray = array;
-        fFactoryArray = NULL;
-        fFactoryCount = 0;
-    }
-    
-    virtual SkTypeface* readTypeface() = 0;
-    virtual SkRefCnt* readRefCnt() = 0;
-    virtual void* readFunctionPtr() = 0;
-    virtual SkFlattenable* readFlattenable() = 0;
-
-protected:
-    SkRefCnt** fRCArray;
-    int        fRCCount;
-    
-    SkTypeface** fTFArray;
-    int        fTFCount;
-    
-    SkTDArray<SkFlattenable::Factory>* fFactoryTDArray;
-    SkFlattenable::Factory* fFactoryArray;
-    int                     fFactoryCount;
-
-private:
-    uint32_t    fFlags;
-};
-
 ///////////////////////////////////////////////////////////////////////////////
 
 #include "SkPtrRecorder.h"
@@ -268,89 +151,4 @@
     SkTDArray<const char*> fNames;
 };
 
-class SkFlattenableWriteBuffer {
-public:
-    SkFlattenableWriteBuffer();
-    virtual ~SkFlattenableWriteBuffer();
-
-    // deprecated naming convention that will be removed after callers are updated
-    virtual bool writeBool(bool value) = 0;
-    virtual void writeInt(int32_t value) = 0;
-    virtual void write8(int32_t value) = 0;
-    virtual void write16(int32_t value) = 0;
-    virtual void write32(int32_t value) = 0;
-    virtual void writeScalar(SkScalar value) = 0;
-    virtual void writeMul4(const void* values, size_t size) = 0;
-
-    virtual void writePad(const void* src, size_t size) = 0;
-    virtual void writeString(const char* str, size_t len = (size_t)-1) = 0;
-    virtual uint32_t* reserve(size_t size) = 0;
-    virtual void flatten(void* dst) = 0;
-    virtual uint32_t size() = 0;
-    virtual void write(const void* values, size_t size) = 0;
-    virtual void writeRect(const SkRect& rect) = 0;
-    virtual size_t readFromStream(SkStream*, size_t length) = 0;
-
-    virtual void writeMatrix(const SkMatrix& matrix) = 0;
-    virtual void writePath(const SkPath& path) = 0;
-    virtual void writePoint(const SkPoint& point) = 0;
-
-    virtual bool writeToStream(SkWStream*) = 0;
-
-    virtual void writeFunctionPtr(void*)= 0;
-    virtual void writeFlattenable(SkFlattenable* flattenable)= 0;
-
-    void writeTypeface(SkTypeface*);
-    void writeRefCnt(SkRefCnt* obj);
-
-    SkRefCntSet* getTypefaceRecorder() const { return fTFSet; }
-    SkRefCntSet* setTypefaceRecorder(SkRefCntSet*);
-
-    SkRefCntSet* getRefCntRecorder() const { return fRCSet; }
-    SkRefCntSet* setRefCntRecorder(SkRefCntSet*);
-
-    SkFactorySet* getFactoryRecorder() const { return fFactorySet; }
-    SkFactorySet* setFactoryRecorder(SkFactorySet*);
-
-    SkNamedFactorySet* getNamedFactoryRecorder() const { return fNamedFactorySet; }
-    SkNamedFactorySet* setNamedFactoryRecorder(SkNamedFactorySet*);
-
-    enum Flags {
-        kCrossProcess_Flag               = 0x01,
-        /**
-         *  Instructs the writer to always serialize bitmap pixel data.
-         */
-        kForceFlattenBitmapPixels_Flag   = 0x04
-    };
-
-    uint32_t getFlags() const { return fFlags; }
-    void setFlags(uint32_t flags) { fFlags = flags; }
-
-    bool isCrossProcess() const {
-        return SkToBool(fFlags & kCrossProcess_Flag);
-    }
-
-    bool persistBitmapPixels() const {
-        return (fFlags & (kCrossProcess_Flag | kForceFlattenBitmapPixels_Flag)) != 0;
-    }
-
-    bool persistTypeface() const { return (fFlags & kCrossProcess_Flag) != 0; }
-
-protected:
-
-    // A helper function so that each subclass does not have to be a friend of
-    // SkFlattenable.
-    void flattenObject(SkFlattenable* obj, SkFlattenableWriteBuffer& buffer) {
-        obj->flatten(buffer);
-    }
-
-    uint32_t           fFlags;
-    SkRefCntSet*       fTFSet;
-    SkRefCntSet*       fRCSet;
-    SkFactorySet*      fFactorySet;
-    SkNamedFactorySet* fNamedFactorySet;
-
-};
-
 #endif
-
diff --git a/include/core/SkFlattenableBuffers.h b/include/core/SkFlattenableBuffers.h
new file mode 100644
index 0000000..d87539e
--- /dev/null
+++ b/include/core/SkFlattenableBuffers.h
@@ -0,0 +1,193 @@
+
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFlattenableBuffers_DEFINED
+#define SkFlattenableBuffers_DEFINED
+
+#include "SkColor.h"
+#include "SkPaint.h"
+#include "SkPoint.h"
+
+class SkBitmap;
+class SkFlattenable;
+struct SkIRect;
+class SkMatrix;
+class SkOrderedReadBuffer;
+class SkOrderedWriteBuffer;
+class SkPath;
+class SkPixelRef;
+struct SkRect;
+class SkRefCnt;
+class SkRegion;
+class SkStream;
+class SkString;
+class SkTypeface;
+class SkWStream;
+
+class SkFlattenableReadBuffer {
+public:
+    SkFlattenableReadBuffer();
+    virtual ~SkFlattenableReadBuffer();
+
+    bool isOrderedBinaryBuffer() { return NULL != getOrderedBinaryBuffer(); }
+    virtual SkOrderedReadBuffer* getOrderedBinaryBuffer() { return NULL; }
+
+    enum Flags {
+        kCrossProcess_Flag      = 1 << 0,
+        kScalarIsFloat_Flag     = 1 << 1,
+        kPtrIs64Bit_Flag        = 1 << 2,
+    };
+
+    void setFlags(uint32_t flags) { fFlags = flags; }
+    uint32_t getFlags() const { return fFlags; }
+
+    bool isCrossProcess() const { return SkToBool(fFlags & kCrossProcess_Flag); }
+    bool isScalarFloat() const { return SkToBool(fFlags & kScalarIsFloat_Flag); }
+    bool isPtr64Bit() const { return SkToBool(fFlags & kPtrIs64Bit_Flag); }
+
+    // primitives
+    virtual bool readBool() = 0;
+    virtual SkColor readColor() = 0;
+    virtual SkFixed readFixed() = 0;
+    virtual int32_t readInt() = 0;
+    virtual SkScalar readScalar() = 0;
+    virtual uint32_t readUInt() = 0;
+    virtual int32_t read32() = 0;
+
+    // strings -- the caller is responsible for freeing the string contents
+    virtual char* readString() = 0;
+    virtual void* readEncodedString(size_t* length, SkPaint::TextEncoding encoding) = 0;
+
+    // common data structures
+    virtual SkFlattenable* readFlattenable() = 0;
+    virtual void readPoint(SkPoint* point) = 0;
+    virtual void readMatrix(SkMatrix* matrix) = 0;
+    virtual void readIRect(SkIRect* rect) = 0;
+    virtual void readRect(SkRect* rect) = 0;
+    virtual void readRegion(SkRegion* region) = 0;
+    virtual void readPath(SkPath* path) = 0;
+
+    // binary data and arrays
+    virtual uint32_t readByteArray(void* value) = 0;
+    virtual uint32_t readColorArray(SkColor* colors) = 0;
+    virtual uint32_t readIntArray(int32_t* values) = 0;
+    virtual uint32_t readPointArray(SkPoint* points) = 0;
+    virtual uint32_t readScalarArray(SkScalar* values) = 0;
+
+    /** This helper peeks into the buffer and reports back the length of the next array in
+     *  the buffer but does not change the state of the buffer.
+     */
+    virtual uint32_t getArrayCount() = 0;
+
+    // helper functions
+    virtual void* readFunctionPtr();
+    virtual void readPaint(SkPaint* paint);
+    virtual SkRefCnt* readRefCntPtr();
+
+    virtual void readBitmap(SkBitmap* bitmap) = 0;
+    virtual SkTypeface* readTypeface() = 0;
+
+    // helper function for classes with const SkPoint members
+    SkPoint readPoint() {
+        SkPoint point;
+        this->readPoint(&point);
+        return point;
+    }
+
+    template <typename T> T* readFlattenableT() {
+        return static_cast<T*>(this->readFlattenable());
+    }
+
+private:
+    uint32_t fFlags;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class SkFlattenableWriteBuffer {
+public:
+    SkFlattenableWriteBuffer();
+    virtual ~SkFlattenableWriteBuffer();
+
+    virtual bool isOrderedBinaryBuffer() { return false; }
+    virtual SkOrderedWriteBuffer* getOrderedBinaryBuffer() { sk_throw(); return NULL; }
+
+    // primitives
+    virtual void writeByteArray(const void* data, size_t size) = 0;
+    virtual void writeBool(bool value) = 0;
+    virtual void writeFixed(SkFixed value) = 0;
+    virtual void writeScalar(SkScalar value) = 0;
+    virtual void writeScalarArray(const SkScalar* value, uint32_t count) = 0;
+    virtual void writeInt(int32_t value) = 0;
+    virtual void writeIntArray(const int32_t* value, uint32_t count) = 0;
+    virtual void writeUInt(uint32_t value) = 0;
+    virtual void write32(int32_t value) = 0; // printf in hex
+    virtual void writeString(const char* value) = 0;
+    virtual void writeEncodedString(const void* value, size_t byteLength,
+                                    SkPaint::TextEncoding encoding) = 0;
+
+    // common data structures
+    virtual void writeFlattenable(SkFlattenable* flattenable) = 0;
+    virtual void writeColor(const SkColor& color) = 0;
+    virtual void writeColorArray(const SkColor* color, uint32_t count) = 0;
+    virtual void writePoint(const SkPoint& point) = 0;
+    virtual void writePointArray(const SkPoint* points, uint32_t count) = 0;
+    virtual void writeMatrix(const SkMatrix& matrix) = 0;
+    virtual void writeIRect(const SkIRect& rect) = 0;
+    virtual void writeRect(const SkRect& rect) = 0;
+    virtual void writeRegion(const SkRegion& region) = 0;
+    virtual void writePath(const SkPath& path) = 0;
+    virtual size_t writeStream(SkStream* stream, size_t length) = 0;
+
+    // helper functions
+    virtual void writeFunctionPtr(void* ptr);
+    virtual void writePaint(const SkPaint& paint);
+    virtual void writeRefCntPtr(SkRefCnt* refCnt);
+
+    virtual void writeBitmap(const SkBitmap& bitmap) = 0;
+    virtual void writeTypeface(SkTypeface* typeface) = 0;
+
+    virtual bool writeToStream(SkWStream*) = 0;
+
+    enum Flags {
+        kCrossProcess_Flag               = 0x01,
+        /**
+         *  Instructs the writer to inline Factory names as there are seen the
+         *  first time (after that we store an index). The pipe code uses this.
+         */
+        kInlineFactoryNames_Flag         = 0x02,
+        /**
+         *  Instructs the writer to always serialize bitmap pixel data.
+         */
+        kForceFlattenBitmapPixels_Flag   = 0x04,
+    };
+
+    uint32_t getFlags() const { return fFlags; }
+    void setFlags(uint32_t flags) { fFlags = flags; }
+
+    bool isCrossProcess() const {
+        return SkToBool(fFlags & kCrossProcess_Flag);
+    }
+    bool inlineFactoryNames() const {
+        return SkToBool(fFlags & kInlineFactoryNames_Flag);
+    }
+
+    bool persistBitmapPixels() const {
+        return (fFlags & (kCrossProcess_Flag | kForceFlattenBitmapPixels_Flag)) != 0;
+    }
+
+    bool persistTypeface() const { return (fFlags & kCrossProcess_Flag) != 0; }
+
+protected:
+    // A helper function so that each subclass does not have to be a friend of SkFlattenable
+    void flattenObject(SkFlattenable* obj, SkFlattenableWriteBuffer& buffer);
+
+    uint32_t fFlags;
+};
+
+#endif
diff --git a/include/core/SkImageFilter.h b/include/core/SkImageFilter.h
index b16fb0f..1c0a051 100644
--- a/include/core/SkImageFilter.h
+++ b/include/core/SkImageFilter.h
@@ -9,11 +9,15 @@
 #define SkImageFilter_DEFINED
 
 #include "SkFlattenable.h"
+#include "SkSize.h"
 
 class SkBitmap;
 class SkDevice;
 class SkMatrix;
+struct SkIPoint;
+struct SkIRect;
 struct SkPoint;
+struct SkRect;
 class GrCustomStage;
 class GrTexture;
 
diff --git a/include/core/SkOrderedReadBuffer.h b/include/core/SkOrderedReadBuffer.h
index 12b74d1..5651e7c 100644
--- a/include/core/SkOrderedReadBuffer.h
+++ b/include/core/SkOrderedReadBuffer.h
@@ -11,52 +11,109 @@
 
 #include "SkRefCnt.h"
 #include "SkBitmap.h"
-#include "SkFlattenable.h"
-#include "SkWriter32.h"
+#include "SkFlattenableBuffers.h"
+#include "SkReader32.h"
 #include "SkPath.h"
 
 class SkOrderedReadBuffer : public SkFlattenableReadBuffer {
 public:
     SkOrderedReadBuffer() : INHERITED() {}
     SkOrderedReadBuffer(const void* data, size_t size);
+    SkOrderedReadBuffer(SkStream* stream);
+    virtual ~SkOrderedReadBuffer();
 
-    void setMemory(const void* data, size_t size) { fReader.setMemory(data, size); }
-    uint32_t size() { return fReader.size(); }
-    const void* base() { return fReader.base(); }
-    uint32_t offset() { return fReader.offset(); }
-    bool eof() { return fReader.eof(); }
-    void rewind() { fReader.rewind(); }
-    void setOffset(size_t offset) { fReader.setOffset(offset); }
+    virtual SkOrderedReadBuffer* getOrderedBinaryBuffer() SK_OVERRIDE { return this; }
 
     SkReader32* getReader32() { return &fReader; }
 
-    virtual uint8_t readU8() { return fReader.readU8(); }
-    virtual uint16_t readU16() { return fReader.readU16(); }
-    virtual uint32_t readU32() { return fReader.readU32(); }
-    virtual void read(void* dst, size_t size) { return fReader.read(dst, size); }
-    virtual bool readBool() { return fReader.readBool(); }
-    virtual int32_t readInt() { return fReader.readInt(); }
-    virtual SkScalar readScalar() { return fReader.readScalar(); }
-    virtual const void* skip(size_t size) { return fReader.skip(size); }
+    uint32_t size() { return fReader.size(); }
+    uint32_t offset() { return fReader.offset(); }
+    bool eof() { return fReader.eof(); }
+    const void* skip(size_t size) { return fReader.skip(size); }
 
-    virtual void readMatrix(SkMatrix* m) { fReader.readMatrix(m); }
-    virtual void readPath(SkPath* p) { fReader.readPath(p); }
+    // primitives
+    virtual bool readBool() SK_OVERRIDE;
+    virtual SkColor readColor() SK_OVERRIDE;
+    virtual SkFixed readFixed() SK_OVERRIDE;
+    virtual int32_t readInt() SK_OVERRIDE;
+    virtual SkScalar readScalar() SK_OVERRIDE;
+    virtual uint32_t readUInt() SK_OVERRIDE;
+    virtual int32_t read32() SK_OVERRIDE;
 
-    virtual void readPoint(SkPoint* p) {
-        p->fX = fReader.readScalar();
-        p->fY = fReader.readScalar();
+    // strings -- the caller is responsible for freeing the string contents
+    virtual char* readString() SK_OVERRIDE;
+    virtual void* readEncodedString(size_t* length, SkPaint::TextEncoding encoding) SK_OVERRIDE;
+
+    // common data structures
+    virtual SkFlattenable* readFlattenable() SK_OVERRIDE;
+    virtual void readPoint(SkPoint* point) SK_OVERRIDE;
+    virtual void readMatrix(SkMatrix* matrix) SK_OVERRIDE;
+    virtual void readIRect(SkIRect* rect) SK_OVERRIDE;
+    virtual void readRect(SkRect* rect) SK_OVERRIDE;
+    virtual void readRegion(SkRegion* region) SK_OVERRIDE;
+    virtual void readPath(SkPath* path) SK_OVERRIDE;
+
+    // binary data and arrays
+    virtual uint32_t readByteArray(void* value) SK_OVERRIDE;
+    virtual uint32_t readColorArray(SkColor* colors) SK_OVERRIDE;
+    virtual uint32_t readIntArray(int32_t* values) SK_OVERRIDE;
+    virtual uint32_t readPointArray(SkPoint* points) SK_OVERRIDE;
+    virtual uint32_t readScalarArray(SkScalar* values) SK_OVERRIDE;
+
+    // helpers to get info about arrays and binary data
+    virtual uint32_t getArrayCount() SK_OVERRIDE;
+
+    virtual SkRefCnt* readRefCntPtr() SK_OVERRIDE;
+
+    virtual void readBitmap(SkBitmap* bitmap) SK_OVERRIDE;
+    virtual SkTypeface* readTypeface() SK_OVERRIDE;
+
+    void setRefCntArray(SkRefCnt* array[], int count) {
+        fRCArray = array;
+        fRCCount = count;
     }
 
-    virtual SkTypeface* readTypeface();
-    virtual SkRefCnt* readRefCnt();
-    virtual void* readFunctionPtr();
-    virtual SkFlattenable* readFlattenable();
+    void setTypefaceArray(SkTypeface* array[], int count) {
+        fTFArray = array;
+        fTFCount = count;
+    }
+
+    /**
+     *  Call this with a pre-loaded array of Factories, in the same order as
+     *  were created/written by the writer. SkPicture uses this.
+     */
+    void setFactoryPlayback(SkFlattenable::Factory array[], int count) {
+        fFactoryTDArray = NULL;
+        fFactoryArray = array;
+        fFactoryCount = count;
+    }
+
+    /**
+     *  Call this with an initially empty array, so the reader can cache each
+     *  factory it sees by name. Used by the pipe code in conjunction with
+     *  the writer's kInlineFactoryNames_Flag.
+     */
+    void setFactoryArray(SkTDArray<SkFlattenable::Factory>* array) {
+        fFactoryTDArray = array;
+        fFactoryArray = NULL;
+        fFactoryCount = 0;
+    }
 
 private:
     SkReader32 fReader;
+    void* fMemoryPtr;
+
+    SkRefCnt** fRCArray;
+    int        fRCCount;
+
+    SkTypeface** fTFArray;
+    int        fTFCount;
+
+    SkTDArray<SkFlattenable::Factory>* fFactoryTDArray;
+    SkFlattenable::Factory* fFactoryArray;
+    int                     fFactoryCount;
 
     typedef SkFlattenableReadBuffer INHERITED;
 };
 
 #endif // SkOrderedReadBuffer_DEFINED
-
diff --git a/include/core/SkOrderedWriteBuffer.h b/include/core/SkOrderedWriteBuffer.h
index 6468719..8cd2d81 100644
--- a/include/core/SkOrderedWriteBuffer.h
+++ b/include/core/SkOrderedWriteBuffer.h
@@ -9,55 +9,81 @@
 #ifndef SkOrderedWriteBuffer_DEFINED
 #define SkOrderedWriteBuffer_DEFINED
 
+#include "SkFlattenableBuffers.h"
+
 #include "SkRefCnt.h"
 #include "SkBitmap.h"
-#include "SkFlattenable.h"
-#include "SkWriter32.h"
 #include "SkPath.h"
+#include "SkWriter32.h"
+
+class SkFlattenable;
 
 class SkOrderedWriteBuffer : public SkFlattenableWriteBuffer {
 public:
     SkOrderedWriteBuffer(size_t minSize);
     SkOrderedWriteBuffer(size_t minSize, void* initialStorage,
                          size_t storageSize);
-    virtual ~SkOrderedWriteBuffer() {}
+    virtual ~SkOrderedWriteBuffer();
+
+    virtual bool isOrderedBinaryBuffer() SK_OVERRIDE { return true; }
+    virtual SkOrderedWriteBuffer* getOrderedBinaryBuffer() SK_OVERRIDE { return this; }
 
     SkWriter32* getWriter32() { return &fWriter; }
 
-    // deprecated naming convention that will be removed after callers are updated
-    virtual bool writeBool(bool value) { return fWriter.writeBool(value); }
-    virtual void writeInt(int32_t value) { fWriter.writeInt(value); }
-    virtual void write8(int32_t value) { fWriter.write8(value); }
-    virtual void write16(int32_t value) { fWriter.write16(value); }
-    virtual void write32(int32_t value) { fWriter.write32(value); }
-    virtual void writeScalar(SkScalar value) { fWriter.writeScalar(value); }
-    virtual void writeMul4(const void* values, size_t size) { fWriter.writeMul4(values, size); }
+    void writeToMemory(void* dst) { fWriter.flatten(dst); }
+    uint32_t* reserve(size_t size) { return fWriter.reserve(size); }
+    uint32_t size() { return fWriter.size(); }
 
-    virtual void writePad(const void* src, size_t size) { fWriter.writePad(src, size); }
-    virtual void writeString(const char* str, size_t len = (size_t)-1) { fWriter.writeString(str, len); }
-    virtual bool writeToStream(SkWStream* stream) { return fWriter.writeToStream(stream); }
-    virtual void write(const void* values, size_t size) { fWriter.write(values, size); }
-    virtual void writeRect(const SkRect& rect) { fWriter.writeRect(rect); }
-    virtual size_t readFromStream(SkStream* s, size_t length) { return fWriter.readFromStream(s, length); }
+    virtual void writeByteArray(const void* data, size_t size) SK_OVERRIDE;
+    virtual void writeBool(bool value) SK_OVERRIDE;
+    virtual void writeFixed(SkFixed value) SK_OVERRIDE;
+    virtual void writeScalar(SkScalar value) SK_OVERRIDE;
+    virtual void writeScalarArray(const SkScalar* value, uint32_t count) SK_OVERRIDE;
+    virtual void writeInt(int32_t value) SK_OVERRIDE;
+    virtual void writeIntArray(const int32_t* value, uint32_t count) SK_OVERRIDE;
+    virtual void writeUInt(uint32_t value) SK_OVERRIDE;
+    virtual void write32(int32_t value) SK_OVERRIDE;
+    virtual void writeString(const char* value) SK_OVERRIDE;
+    virtual void writeEncodedString(const void* value, size_t byteLength,
+                                    SkPaint::TextEncoding encoding) SK_OVERRIDE;
 
-    virtual void writeMatrix(const SkMatrix& matrix) { fWriter.writeMatrix(matrix); }
-    virtual void writePath(const SkPath& path) { fWriter.writePath(path); };
-    virtual void writePoint(const SkPoint& point) {
-        fWriter.writeScalar(point.fX);
-        fWriter.writeScalar(point.fY);
-    }
+    virtual void writeFlattenable(SkFlattenable* flattenable) SK_OVERRIDE;
+    virtual void writeColor(const SkColor& color) SK_OVERRIDE;
+    virtual void writeColorArray(const SkColor* color, uint32_t count) SK_OVERRIDE;
+    virtual void writePoint(const SkPoint& point) SK_OVERRIDE;
+    virtual void writePointArray(const SkPoint* point, uint32_t count) SK_OVERRIDE;
+    virtual void writeMatrix(const SkMatrix& matrix) SK_OVERRIDE;
+    virtual void writeIRect(const SkIRect& rect)SK_OVERRIDE;
+    virtual void writeRect(const SkRect& rect) SK_OVERRIDE;
+    virtual void writeRegion(const SkRegion& region) SK_OVERRIDE;
+    virtual void writePath(const SkPath& path) SK_OVERRIDE;
+    virtual size_t writeStream(SkStream* stream, size_t length) SK_OVERRIDE;
 
-    virtual uint32_t* reserve(size_t size) { return fWriter.reserve(size); }
-    virtual void flatten(void* dst) { fWriter.flatten(dst); }
-    virtual uint32_t size() { return fWriter.size(); }
+    virtual void writeRefCntPtr(SkRefCnt* refCnt) SK_OVERRIDE;
 
-    virtual void writeFunctionPtr(void*);
-    virtual void writeFlattenable(SkFlattenable* flattenable);
+    virtual void writeBitmap(const SkBitmap& bitmap) SK_OVERRIDE;
+    virtual void writeTypeface(SkTypeface* typeface) SK_OVERRIDE;
+
+    virtual bool writeToStream(SkWStream*) SK_OVERRIDE;
+
+    SkFactorySet* setFactoryRecorder(SkFactorySet*);
+    SkNamedFactorySet* setNamedFactoryRecorder(SkNamedFactorySet*);
+
+    SkRefCntSet* getTypefaceRecorder() const { return fTFSet; }
+    SkRefCntSet* setTypefaceRecorder(SkRefCntSet*);
+
+    SkRefCntSet* getRefCntRecorder() const { return fRCSet; }
+    SkRefCntSet* setRefCntRecorder(SkRefCntSet*);
 
 private:
+    SkFactorySet* fFactorySet;
+    SkNamedFactorySet* fNamedFactorySet;
     SkWriter32 fWriter;
+
+    SkRefCntSet*    fRCSet;
+    SkRefCntSet*    fTFSet;
+
     typedef SkFlattenableWriteBuffer INHERITED;
 };
 
 #endif // SkOrderedWriteBuffer_DEFINED
-
diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h
index 4defe8b..0e68f03 100644
--- a/include/core/SkPaint.h
+++ b/include/core/SkPaint.h
@@ -29,6 +29,7 @@
 class SkMatrix;
 class SkPath;
 class SkPathEffect;
+struct SkPoint;
 class SkRasterizer;
 class SkShader;
 class SkTypeface;
diff --git a/include/core/SkShape.h b/include/core/SkShape.h
index 4f2bd98..1a149b1 100644
--- a/include/core/SkShape.h
+++ b/include/core/SkShape.h
@@ -9,6 +9,7 @@
 #define SkShape_DEFINED
 
 #include "SkFlattenable.h"
+#include "SkScalar.h"
 
 class SkCanvas;
 class SkMatrix;
diff --git a/include/effects/SkRectShape.h b/include/effects/SkRectShape.h
index a06adfc..88a3646 100644
--- a/include/effects/SkRectShape.h
+++ b/include/effects/SkRectShape.h
@@ -10,6 +10,7 @@
 
 #include "SkShape.h"
 #include "SkPaint.h"
+#include "SkRect.h"
 #include "SkSize.h"
 
 class SkPaintShape : public SkShape {
diff --git a/include/effects/SkTestImageFilters.h b/include/effects/SkTestImageFilters.h
index a28ed8b..bb873e9 100755
--- a/include/effects/SkTestImageFilters.h
+++ b/include/effects/SkTestImageFilters.h
@@ -4,6 +4,7 @@
 
 #include "SkImageFilter.h"
 #include "SkColorFilter.h"
+#include "SkPoint.h"
 
 class SkOffsetImageFilter : public SkImageFilter {
 public:
diff --git a/samplecode/ClockFaceView.cpp b/samplecode/ClockFaceView.cpp
index 7d4da10..a719608 100644
--- a/samplecode/ClockFaceView.cpp
+++ b/samplecode/ClockFaceView.cpp
@@ -8,6 +8,7 @@
 #include "SampleCode.h"
 #include "SkView.h"
 #include "SkCanvas.h"
+#include "SkFlattenableBuffers.h"
 #include "SkGradientShader.h"
 #include "SkPath.h"
 #include "SkRegion.h"
diff --git a/samplecode/SampleAll.cpp b/samplecode/SampleAll.cpp
index 303059b..9644e79 100644
--- a/samplecode/SampleAll.cpp
+++ b/samplecode/SampleAll.cpp
@@ -18,6 +18,7 @@
 #include "SkDashPathEffect.h"
 #include "SkDiscretePathEffect.h"
 #include "SkEmbossMaskFilter.h"
+#include "SkFlattenableBuffers.h"
 #include "SkGradientShader.h"
 #include "SkImageDecoder.h"
 #include "SkLayerRasterizer.h"
diff --git a/samplecode/SampleSlides.cpp b/samplecode/SampleSlides.cpp
index 1154c76..54a9cf9 100644
--- a/samplecode/SampleSlides.cpp
+++ b/samplecode/SampleSlides.cpp
@@ -9,6 +9,7 @@
 #include "SkView.h"
 #include "SkCanvas.h"
 #include "SkDevice.h"
+#include "SkFlattenableBuffers.h"
 #include "SkPaint.h"
 
 #define BG_COLOR    0xFFDDDDDD
diff --git a/samplecode/SampleText.cpp b/samplecode/SampleText.cpp
index db4dbea..7d192f4 100644
--- a/samplecode/SampleText.cpp
+++ b/samplecode/SampleText.cpp
@@ -9,6 +9,7 @@
 #include "SkView.h"
 #include "SkCanvas.h"
 #include "Sk64.h"
+#include "SkFlattenableBuffers.h"
 #include "SkGradientShader.h"
 #include "SkGraphics.h"
 #include "SkImageDecoder.h"
@@ -134,11 +135,11 @@
     void init(SkScalar exponent);
     SkPowerMode(SkFlattenableReadBuffer& b) : INHERITED(b) {
         // read the exponent
-        this->init(SkFixedToScalar(b.readS32()));
+        this->init(SkFixedToScalar(b.readFixed()));
     }
     virtual void flatten(SkFlattenableWriteBuffer& b) const SK_OVERRIDE {
         this->INHERITED::flatten(b);
-        b.write32(SkScalarToFixed(fExp));
+        b.writeFixed(SkScalarToFixed(fExp));
     }
 
     typedef SkXfermode INHERITED;
diff --git a/samplecode/SampleTextEffects.cpp b/samplecode/SampleTextEffects.cpp
index 2151548..b2feae7 100644
--- a/samplecode/SampleTextEffects.cpp
+++ b/samplecode/SampleTextEffects.cpp
@@ -8,6 +8,7 @@
 #include "SampleCode.h"
 #include "SkView.h"
 #include "SkCanvas.h"
+#include "SkFlattenableBuffers.h"
 #include "SkGradientShader.h"
 #include "SkPath.h"
 #include "SkRegion.h"
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);
 }
 
diff --git a/tests/ColorFilterTest.cpp b/tests/ColorFilterTest.cpp
index 6bfd9f2..7cfb467 100644
--- a/tests/ColorFilterTest.cpp
+++ b/tests/ColorFilterTest.cpp
@@ -20,7 +20,7 @@
     size_t size = wb.size();
     SkAutoSMalloc<1024> storage(size);
     // make a copy into storage
-    wb.flatten(storage.get());
+    wb.writeToMemory(storage.get());
 
     SkOrderedReadBuffer rb(storage.get(), size);
     return rb.readFlattenable();