GrTArray->SkTArray & docs

Review URL: http://codereview.appspot.com/5005045/



git-svn-id: http://skia.googlecode.com/svn/trunk@2265 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/include/GrAllocator.h b/gpu/include/GrAllocator.h
index ae46938..7652be3 100755
--- a/gpu/include/GrAllocator.h
+++ b/gpu/include/GrAllocator.h
@@ -12,7 +12,7 @@
 #define GrAllocator_DEFINED
 
 #include "GrConfig.h"
-#include "GrTArray.h"
+#include "SkTArray.h"
 
 class GrAllocator {
 public:
@@ -128,7 +128,7 @@
 private:
     static const int NUM_INIT_BLOCK_PTRS = 8;
     
-    GrTArray<void*> fBlocks;
+    SkTArray<void*> fBlocks;
     size_t          fBlockSize;
     char            fBlockInitialStorage[NUM_INIT_BLOCK_PTRS*sizeof(void*)];
     size_t          fItemSize;
@@ -163,7 +163,7 @@
      *                          and the size of subsequent blocks.
      */
     template <int N>
-    GrTAllocator(GrAlignedSTStorage<N,T>* initialBlock)
+    GrTAllocator(SkAlignedSTStorage<N,T>* initialBlock)
         : fAllocator(sizeof(T), N, initialBlock->get()) {}
     
     /**
diff --git a/gpu/include/GrClip.h b/gpu/include/GrClip.h
index 4abd8da..9e235bf 100644
--- a/gpu/include/GrClip.h
+++ b/gpu/include/GrClip.h
@@ -14,9 +14,9 @@
 #include "GrClipIterator.h"
 #include "GrRect.h"
 #include "GrPath.h"
-#include "GrTArray.h"
 #include "GrTemplates.h"
 
+#include "SkTArray.h"
 
 class GrClip {
 public:
@@ -135,8 +135,8 @@
     enum {
         kPreAllocElements = 4,
     };
-    GrAlignedSTStorage<kPreAllocElements, Element>  fListStorage;
-    GrTArray<Element>   fList;
+    SkAlignedSTStorage<kPreAllocElements, Element>  fListStorage;
+    SkTArray<Element>   fList;
 };
 #endif
 
diff --git a/gpu/include/GrTArray.h b/gpu/include/GrTArray.h
deleted file mode 100644
index 5477d25..0000000
--- a/gpu/include/GrTArray.h
+++ /dev/null
@@ -1,335 +0,0 @@
-
-/*
- * Copyright 2010 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-
-#ifndef GrTArray_DEFINED
-#define GrTArray_DEFINED
-
-#include <new>
-#include "GrTypes.h"
-#include "GrTemplates.h"
-
-// DATA_TYPE indicates that T has a trivial cons, destructor
-// and can be shallow-copied
-template <typename T, bool DATA_TYPE = false> class GrTArray {
-public:
-    GrTArray() {
-        fCount = 0;
-        fReserveCount = MIN_ALLOC_COUNT;
-        fAllocCount = 0;
-        fMemArray = NULL;
-        fPreAllocMemArray = NULL;
-    }
-
-    explicit GrTArray(int reserveCount) {
-        GrAssert(reserveCount >= 0);
-        fCount = 0;
-        fReserveCount = reserveCount > MIN_ALLOC_COUNT ? reserveCount :
-                                                         MIN_ALLOC_COUNT;
-        fAllocCount = fReserveCount;
-        fMemArray = GrMalloc(sizeof(T) * fReserveCount);
-        fPreAllocMemArray = NULL;
-    }
-
-    template <int N>
-    GrTArray(GrAlignedSTStorage<N,T>* storage) {
-        GrAssert(N > 0);
-        fCount              = 0;
-        fReserveCount       = N;
-        fAllocCount         = N;
-        fMemArray           = storage->get();
-        fPreAllocMemArray   = storage->get();
-    }
-
-    GrTArray(void* preAllocStorage, int preAllocCount) {
-        GrAssert(preAllocCount >= 0);
-        // we allow NULL,0 args and revert to the default cons. behavior
-        // this makes it possible for a owner-object to use same constructor
-        // to get either prealloc or nonprealloc behavior based using same line
-        GrAssert((NULL == preAllocStorage) == !preAllocCount);
-
-        fCount              = 0;
-        fReserveCount       = preAllocCount > 0 ? preAllocCount :
-                                                  MIN_ALLOC_COUNT;
-        fAllocCount         = preAllocCount;
-        fMemArray           = preAllocStorage;
-        fPreAllocMemArray   = preAllocStorage;
-    }
-
-    explicit GrTArray(const GrTArray& array) {
-        fCount              = array.count();
-        fReserveCount       = MIN_ALLOC_COUNT;
-        fAllocCount         = GrMax(fReserveCount, fCount);
-        fMemArray           = GrMalloc(sizeof(T) * fAllocCount);
-        fPreAllocMemArray   = NULL;
-
-        if (DATA_TYPE) {
-            memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
-        } else {
-            for (int i = 0; i < fCount; ++i) {
-                new (fItemArray + i) T(array[i]);
-            }
-        }
-    }
-
-    GrTArray(const T* array, int count) {
-        GrAssert(count >= 0);
-        fCount              = count;
-        fReserveCount       = MIN_ALLOC_COUNT;
-        fAllocCount         = GrMax(fReserveCount, fCount);
-        fMemArray           = GrMalloc(sizeof(T) * fAllocCount);
-        fPreAllocMemArray   = NULL;
-        if (DATA_TYPE) {
-            memcpy(fMemArray, array, sizeof(T) * fCount);
-        } else {
-            for (int i = 0; i < fCount; ++i) {
-                new (fItemArray + i) T(array[i]);
-            }
-        }
-    }
-
-    GrTArray(const GrTArray& array,
-             void* preAllocStorage, int preAllocCount) {
-
-        GrAssert(preAllocCount >= 0);
-
-        // for same reason as non-copying cons we allow NULL, 0 for prealloc
-        GrAssert((NULL == preAllocStorage) == !preAllocCount);
-
-        fCount              = array.count();
-        fReserveCount       = preAllocCount > 0 ? preAllocCount :
-                                                  MIN_ALLOC_COUNT;
-        fPreAllocMemArray   = preAllocStorage;
-
-        if (fReserveCount >= fCount && preAllocCount) {
-            fAllocCount = fReserveCount;
-            fMemArray = preAllocStorage;
-        } else {
-            fAllocCount = GrMax(fCount, fReserveCount);
-            fMemArray = GrMalloc(fAllocCount * sizeof(T));
-        }
-
-        if (DATA_TYPE) {
-            memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
-        } else {
-            for (int i = 0; i < fCount; ++i) {
-                new (fItemArray + i) T(array[i]);
-            }
-        }
-    }
-
-    GrTArray(const T* array, int count,
-             void* preAllocStorage, int preAllocCount) {
-
-        GrAssert(count >= 0);
-        GrAssert(preAllocCount >= 0);
-
-        // for same reason as non-copying cons we allow NULL, 0 for prealloc
-        GrAssert((NULL == preAllocStorage) == !preAllocCount);
-
-        fCount              = count;
-        fReserveCount       = (preAllocCount > 0) ? preAllocCount :
-                                                    MIN_ALLOC_COUNT;
-        fPreAllocMemArray   = preAllocStorage;
-
-        if (fReserveCount >= fCount && preAllocCount) {
-            fAllocCount = fReserveCount;
-            fMemArray = preAllocStorage;
-        } else {
-            fAllocCount = GrMax(fCount, fReserveCount);
-            fMemArray = GrMalloc(fAllocCount * sizeof(T));
-        }
-
-        if (DATA_TYPE) {
-            memcpy(fMemArray, array, sizeof(T) * fCount);
-        } else {
-            for (int i = 0; i < fCount; ++i) {
-                new (fItemArray + i) T(array[i]);
-            }
-        }
-    }
-
-    GrTArray& operator =(const GrTArray& array) {
-        for (int i = 0; i < fCount; ++i) {
-            fItemArray[i].~T();
-        }
-        fCount = 0;
-        checkRealloc((int)array.count());
-        fCount = array.count();
-        if (DATA_TYPE) {
-            memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
-        } else {
-            for (int i = 0; i < fCount; ++i) {
-                new (fItemArray + i) T(array[i]);
-            }
-        }
-        return *this;
-    }
-
-    ~GrTArray() {
-        for (int i = 0; i < fCount; ++i) {
-            fItemArray[i].~T();
-        }
-        if (fMemArray != fPreAllocMemArray) {
-            GrFree(fMemArray);
-        }
-    }
-
-    void reset() { this->pop_back_n(fCount); }
-
-    int count() const { return fCount; }
-
-    bool empty() const { return !fCount; }
-
-    /**
-     * Adds 1 new default-constructed T value and returns in by reference. Note
-     * the reference only remains valid until the next call that adds or removes
-     * elements.
-     */
-    T& push_back() {
-        checkRealloc(1);
-        new ((char*)fMemArray+sizeof(T)*fCount) T;
-        ++fCount;
-        return fItemArray[fCount-1];
-    }
-
-    /**
-     * Allocates n more default T values, and returns the address of the start
-     * of that new range. Note: this address is only valid until the next API
-     * call made on the array that might add or remove elements.
-     */
-    T* push_back_n(int n) {
-        GrAssert(n >= 0);
-        checkRealloc(n);
-        for (int i = 0; i < n; ++i) {
-            new (fItemArray + fCount + i) T;
-        }
-        fCount += n;
-        return fItemArray + fCount - n;
-    }
-
-    void pop_back() {
-        GrAssert(fCount > 0);
-        --fCount;
-        fItemArray[fCount].~T();
-        checkRealloc(0);
-    }
-
-    void pop_back_n(int n) {
-        GrAssert(n >= 0);
-        GrAssert(fCount >= n);
-        fCount -= n;
-        for (int i = 0; i < n; ++i) {
-            fItemArray[i].~T();
-        }
-        checkRealloc(0);
-    }
-
-    // pushes or pops from the back to resize
-    void resize_back(int newCount) {
-        GrAssert(newCount >= 0);
-
-        if (newCount > fCount) {
-            push_back_n(newCount - fCount);
-        } else if (newCount < fCount) {
-            pop_back_n(fCount - newCount);
-        }
-    }
-
-    T& operator[] (int i) {
-        GrAssert(i < fCount);
-        GrAssert(i >= 0);
-        return fItemArray[i];
-    }
-
-    const T& operator[] (int i) const {
-        GrAssert(i < fCount);
-        GrAssert(i >= 0);
-        return fItemArray[i];
-    }
-
-    T& front() { GrAssert(fCount > 0); return fItemArray[0];}
-
-    const T& front() const { GrAssert(fCount > 0); return fItemArray[0];}
-
-    T& back() { GrAssert(fCount); return fItemArray[fCount - 1];}
-
-    const T& back() const { GrAssert(fCount > 0); return fItemArray[fCount - 1];}
-
-    T& fromBack(int i) {
-        GrAssert(i >= 0);
-        GrAssert(i < fCount);
-        return fItemArray[fCount - i - 1];
-    }
-
-    const T& fromBack(int i) const {
-        GrAssert(i >= 0);
-        GrAssert(i < fCount);
-        return fItemArray[fCount - i - 1];
-    }
-
-private:
-
-    static const int MIN_ALLOC_COUNT = 8;
-
-    inline void checkRealloc(int delta) {
-        GrAssert(fCount >= 0);
-        GrAssert(fAllocCount >= 0);
-
-        GrAssert(-delta <= fCount);
-
-        int newCount = fCount + delta;
-        int fNewAllocCount = fAllocCount;
-
-        if (newCount > fAllocCount) {
-            fNewAllocCount = GrMax(newCount + ((newCount + 1) >> 1),
-                                   fReserveCount);
-        } else if (newCount < fAllocCount / 3) {
-            fNewAllocCount = GrMax(fAllocCount / 2, fReserveCount);
-        }
-
-        if (fNewAllocCount != fAllocCount) {
-
-            fAllocCount = fNewAllocCount;
-            char* fNewMemArray;
-
-            if (fAllocCount == fReserveCount && NULL != fPreAllocMemArray) {
-                fNewMemArray = (char*) fPreAllocMemArray;
-            } else {
-                fNewMemArray = (char*) GrMalloc(fAllocCount*sizeof(T));
-            }
-
-            if (DATA_TYPE) {
-                memcpy(fNewMemArray, fMemArray, fCount * sizeof(T));
-            } else {
-                for (int i = 0; i < fCount; ++i) {
-                    new (fNewMemArray + sizeof(T) * i) T(fItemArray[i]);
-                    fItemArray[i].~T();
-                }
-            }
-
-            if (fMemArray != fPreAllocMemArray) {
-                GrFree(fMemArray);
-            }
-            fMemArray = fNewMemArray;
-        }
-    }
-
-    int fReserveCount;
-    int fCount;
-    int fAllocCount;
-    void*    fPreAllocMemArray;
-    union {
-        T*       fItemArray;
-        void*    fMemArray;
-    };
-};
-
-#endif
-
diff --git a/gpu/include/GrTemplates.h b/gpu/include/GrTemplates.h
index 9ffa51b..63e43ee 100644
--- a/gpu/include/GrTemplates.h
+++ b/gpu/include/GrTemplates.h
@@ -25,38 +25,6 @@
 }
 
 /**
- * Reserves memory that is aligned on double and pointer boundaries.
- * Hopefully this is sufficient for all practical purposes.
- */
-template <size_t N> class GrAlignedSStorage : GrNoncopyable {
-public:
-    void* get() { return fData; }
-private:
-    union {
-        void*   fPtr;
-        double  fDouble;
-        char    fData[N];
-    };
-};
-
-/**
- * Reserves memory that is aligned on double and pointer boundaries.
- * Hopefully this is sufficient for all practical purposes. Otherwise,
- * we have to do some arcane trickery to determine alignment of non-POD
- * types. Lifetime of the memory is the lifetime of the object.
- */
-template <int N, typename T> class GrAlignedSTStorage : GrNoncopyable {
-public:
-    /**
-     * Returns void* because this object does not initialize the
-     * memory. Use placement new for types that require a cons.
-     */
-    void* get() { return fStorage.get(); }
-private:
-    GrAlignedSStorage<sizeof(T)*N> fStorage;
-};
-
-/**
  * saves value of T* in and restores in destructor
  * e.g.:
  * {
diff --git a/gpu/src/GrAAHairLinePathRenderer.cpp b/gpu/src/GrAAHairLinePathRenderer.cpp
index f60e7cf..d57aa3a 100644
--- a/gpu/src/GrAAHairLinePathRenderer.cpp
+++ b/gpu/src/GrAAHairLinePathRenderer.cpp
@@ -137,8 +137,8 @@
 
 namespace {
 
-typedef GrTArray<SkPoint, true> PtArray;
-typedef GrTArray<int, true> IntArray;
+typedef SkTArray<SkPoint, true> PtArray;
+typedef SkTArray<int, true> IntArray;
 
 /**
  * We convert cubics to quadratics (for now).
@@ -633,8 +633,8 @@
 
     GrMatrix viewM = fTarget->getViewMatrix();
 
-    GrAlignedSTStorage<128, GrPoint> lineStorage;
-    GrAlignedSTStorage<128, GrPoint> quadStorage;
+    SkAlignedSTStorage<128, GrPoint> lineStorage;
+    SkAlignedSTStorage<128, GrPoint> quadStorage;
     PtArray lines(&lineStorage);
     PtArray quads(&quadStorage);
     IntArray qSubdivs;
diff --git a/gpu/src/GrBufferAllocPool.h b/gpu/src/GrBufferAllocPool.h
index f9d9e19..acf0289 100644
--- a/gpu/src/GrBufferAllocPool.h
+++ b/gpu/src/GrBufferAllocPool.h
@@ -13,7 +13,8 @@
 
 #include "GrNoncopyable.h"
 #include "GrTDArray.h"
-#include "GrTArray.h"
+
+#include "SkTArray.h"
 
 class GrGeometryBuffer;
 class GrGpu;
@@ -173,7 +174,7 @@
     size_t                          fMinBlockSize;
     BufferType                      fBufferType;
 
-    GrTArray<BufferBlock>           fBlocks;
+    SkTArray<BufferBlock>           fBlocks;
     int                             fPreallocBuffersInUse;
     int                             fFirstPreallocBuffer;
     SkAutoMalloc                    fCpuData;
diff --git a/gpu/src/GrDrawTarget.h b/gpu/src/GrDrawTarget.h
index 42723f6..1d61a18 100644
--- a/gpu/src/GrDrawTarget.h
+++ b/gpu/src/GrDrawTarget.h
@@ -1315,10 +1315,10 @@
     enum {
         kPreallocGeoSrcStateStackCnt = 4,
     };
-    GrAlignedSTStorage<kPreallocGeoSrcStateStackCnt, 
+    SkAlignedSTStorage<kPreallocGeoSrcStateStackCnt, 
                         GeometrySrcState> 
                                      fGeoSrcStateStackStorage;
-    GrTArray<GeometrySrcState, true> fGeoSrcStateStack;
+    SkTArray<GeometrySrcState, true> fGeoSrcStateStack;
     
 };
 
diff --git a/gpu/src/GrGpu.h b/gpu/src/GrGpu.h
index 88b50b1..e970554 100644
--- a/gpu/src/GrGpu.h
+++ b/gpu/src/GrGpu.h
@@ -509,9 +509,9 @@
     enum {
         kPreallocGeomPoolStateStackCnt = 4,
     };
-    GrAlignedSTStorage<kPreallocGeomPoolStateStackCnt, 
+    SkAlignedSTStorage<kPreallocGeomPoolStateStackCnt, 
                        GeometryPoolState>           fGeoSrcStateStackStorage;
-    GrTArray<GeometryPoolState, true>               fGeomPoolStateStack;
+    SkTArray<GeometryPoolState, true>               fGeomPoolStateStack;
     
     mutable GrIndexBuffer*      fQuadIndexBuffer; // mutable so it can be
                                                   // created on-demand
diff --git a/gpu/src/GrGpuGL.h b/gpu/src/GrGpuGL.h
index 47aca3c..b1accf6 100644
--- a/gpu/src/GrGpuGL.h
+++ b/gpu/src/GrGpuGL.h
@@ -194,7 +194,7 @@
     friend class GrGLRenderTarget;
 
 
-    GrTArray<GrGLStencilBuffer::Format, true> fStencilFormats;
+    SkTArray<GrGLStencilBuffer::Format, true> fStencilFormats;
     // we want to clear stencil buffers when they are created. We want to clear
     // the entire buffer even if it is larger than the color attachment. We
     // attach it to this fbo with no color attachment to do the initial clear.
diff --git a/gpu/src/GrInOrderDrawBuffer.h b/gpu/src/GrInOrderDrawBuffer.h
index dbf6144..f0b5c9e 100644
--- a/gpu/src/GrInOrderDrawBuffer.h
+++ b/gpu/src/GrInOrderDrawBuffer.h
@@ -172,7 +172,7 @@
         size_t                          fUsedPoolVertexBytes;
         size_t                          fUsedPoolIndexBytes;
     };
-    GrTArray<GeometryPoolState> fGeoPoolStateStack;
+    SkTArray<GeometryPoolState> fGeoPoolStateStack;
 
     
     enum {
@@ -183,11 +183,11 @@
         kGeoPoolStatePreAllocCnt = 4,
     };
 
-    GrAlignedSTStorage<kDrawPreallocCnt, Draw>              fDrawStorage;
-    GrAlignedSTStorage<kStatePreallocCnt, SavedDrawState>   fStateStorage;
-    GrAlignedSTStorage<kClipPreallocCnt, GrClip>            fClipStorage;
-    GrAlignedSTStorage<kClearPreallocCnt, Clear>            fClearStorage;
-    GrAlignedSTStorage<kGeoPoolStatePreAllocCnt, 
+    SkAlignedSTStorage<kDrawPreallocCnt, Draw>              fDrawStorage;
+    SkAlignedSTStorage<kStatePreallocCnt, SavedDrawState>   fStateStorage;
+    SkAlignedSTStorage<kClipPreallocCnt, GrClip>            fClipStorage;
+    SkAlignedSTStorage<kClearPreallocCnt, Clear>            fClearStorage;
+    SkAlignedSTStorage<kGeoPoolStatePreAllocCnt, 
                         GeometryPoolState>                  fGeoStackStorage;
 
     typedef GrDrawTarget INHERITED;
diff --git a/gpu/src/GrPathRenderer.h b/gpu/src/GrPathRenderer.h
index 815da47..b8e7a4c 100644
--- a/gpu/src/GrPathRenderer.h
+++ b/gpu/src/GrPathRenderer.h
@@ -11,9 +11,10 @@
 #define GrPathRenderer_DEFINED
 
 #include "GrDrawTarget.h"
-#include "GrTArray.h"
 #include "GrPathRendererChain.h"
 
+#include "SkTArray.h"
+
 class SkPath;
 
 struct GrPoint;
diff --git a/gpu/src/GrPathRendererChain.h b/gpu/src/GrPathRendererChain.h
index 0f4305b..24abda4 100644
--- a/gpu/src/GrPathRendererChain.h
+++ b/gpu/src/GrPathRendererChain.h
@@ -11,7 +11,7 @@
 #define GrPathRendererChain_DEFINED
 
 #include "GrRefCnt.h"
-#include "GrTArray.h"
+#include "SkTArray.h"
 
 class GrContext;
 class GrDrawTarget;
@@ -55,8 +55,8 @@
     bool fInit;
     GrContext*                                          fOwner;
     UsageFlags                                          fFlags;
-    GrAlignedSTStorage<kPreAllocCount, GrPathRenderer*> fStorage;
-    GrTArray<GrPathRenderer*, true>                     fChain;
+    SkAlignedSTStorage<kPreAllocCount, GrPathRenderer*> fStorage;
+    SkTArray<GrPathRenderer*, true>                     fChain;
 };
 
 GR_MAKE_BITFIELD_OPS(GrPathRendererChain::UsageFlags)
diff --git a/gyp/gpu.gyp b/gyp/gpu.gyp
index ae05baa..dc113d1 100644
--- a/gyp/gpu.gyp
+++ b/gyp/gpu.gyp
@@ -115,7 +115,6 @@
         '../gpu/include/GrStencil.h',
         '../gpu/include/GrStopwatch.h',
         '../gpu/include/GrStringBuilder.h',
-        '../gpu/include/GrTArray.h',
         '../gpu/include/GrTBSearch.h',
         '../gpu/include/GrTDArray.h',
         '../gpu/include/GrTextContext.h',
diff --git a/include/core/SkTArray.h b/include/core/SkTArray.h
new file mode 100644
index 0000000..7d74b6a
--- /dev/null
+++ b/include/core/SkTArray.h
@@ -0,0 +1,402 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+
+#ifndef SkTArray_DEFINED
+#define SkTArray_DEFINED
+
+#include <new>
+#include "SkTypes.h"
+#include "SkTemplates.h"
+
+// DATA_TYPE indicates that T has a trivial cons, destructor
+// and can be shallow-copied
+template <typename T, bool DATA_TYPE = false> class SkTArray {
+public:
+    /**
+     * Creates an empty array with no initial storage
+     */
+    SkTArray() {
+        fCount = 0;
+        fReserveCount = gMIN_ALLOC_COUNT;
+        fAllocCount = 0;
+        fMemArray = NULL;
+        fPreAllocMemArray = NULL;
+    }
+
+    /**
+     * Creates an empty array that will preallocate space for reserveCount 
+     * elements.
+     */
+    explicit SkTArray(int reserveCount) {
+        SkASSERT(reserveCount >= 0);
+        fCount = 0;
+        fReserveCount = reserveCount > gMIN_ALLOC_COUNT ? reserveCount :
+                                                          gMIN_ALLOC_COUNT;
+        fAllocCount = fReserveCount;
+        fMemArray = sk_malloc_throw(sizeof(T) * fReserveCount);
+        fPreAllocMemArray = NULL;
+    }
+
+    /**
+     * Creates an empty array that will use the passed storage block until it
+     * is insufficiently large to hold the entire array.
+     */
+    template <int N>
+    SkTArray(SkAlignedSTStorage<N,T>* storage) {
+        SkASSERT(N > 0);
+        fCount              = 0;
+        fReserveCount       = N;
+        fAllocCount         = N;
+        fMemArray           = storage->get();
+        fPreAllocMemArray   = storage->get();
+    }
+
+    /**
+     * Creates an empty array that will use the passed memory block until the
+     * count exceeds preAllocCount. Be careful not to use this constructor
+     * when you really want the (T*, int) version.
+     */
+    SkTArray(void* preAllocStorage, int preAllocCount) {
+        SkASSERT(preAllocCount >= 0);
+        // we allow NULL,0 args and revert to the default cons. behavior
+        // this makes it possible for a owner-object to use same constructor
+        // to get either prealloc or nonprealloc behavior based using same line
+        SkASSERT((NULL == preAllocStorage) == !preAllocCount);
+
+        fCount              = 0;
+        fReserveCount       = preAllocCount > 0 ? preAllocCount :
+                                                  gMIN_ALLOC_COUNT;
+        fAllocCount         = preAllocCount;
+        fMemArray           = preAllocStorage;
+        fPreAllocMemArray   = preAllocStorage;
+    }
+
+    /**
+     * Copies one array to another. The new array will be heap allocated.
+     */
+    explicit SkTArray(const SkTArray& array) {
+        fCount              = array.count();
+        fReserveCount       = gMIN_ALLOC_COUNT;
+        fAllocCount         = SkMax32(fReserveCount, fCount);
+        fMemArray           = sk_malloc(sizeof(T) * fAllocCount);
+        fPreAllocMemArray   = NULL;
+
+        if (DATA_TYPE) {
+            memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
+        } else {
+            for (int i = 0; i < fCount; ++i) {
+                new (fItemArray + i) T(array[i]);
+            }
+        }
+    }
+
+    /**
+     * Creates a SkTArray by copying contents of a standard C array. The new 
+     * array will be heap allocated. Be careful not to use this constructor
+     * when you really want the (void*, int) version.
+     */
+    SkTArray(const T* array, int count) {
+        SkASSERT(count >= 0);
+        fCount              = count;
+        fReserveCount       = gMIN_ALLOC_COUNT;
+        fAllocCount         = SkMax32(fReserveCount, fCount);
+        fMemArray           = sk_malloc(sizeof(T) * fAllocCount);
+        fPreAllocMemArray   = NULL;
+        if (DATA_TYPE) {
+            memcpy(fMemArray, array, sizeof(T) * fCount);
+        } else {
+            for (int i = 0; i < fCount; ++i) {
+                new (fItemArray + i) T(array[i]);
+            }
+        }
+    }
+
+    /**
+     * Copy another array, using preallocated storage if preAllocCount >=
+     * array.count(). Otherwise preAllocStorage is only used if the array
+     * shrinks to fit.
+     */
+    SkTArray(const SkTArray& array,
+             void* preAllocStorage, int preAllocCount) {
+
+        SkASSERT(preAllocCount >= 0);
+
+        // for same reason as non-copying cons we allow NULL, 0 for prealloc
+        SkASSERT((NULL == preAllocStorage) == !preAllocCount);
+
+        fCount              = array.count();
+        fReserveCount       = preAllocCount > 0 ? preAllocCount :
+                                                  gMIN_ALLOC_COUNT;
+        fPreAllocMemArray   = preAllocStorage;
+
+        if (fReserveCount >= fCount && preAllocCount) {
+            fAllocCount = fReserveCount;
+            fMemArray = preAllocStorage;
+        } else {
+            fAllocCount = SkMax32(fCount, fReserveCount);
+            fMemArray = sk_malloc_throw(fAllocCount * sizeof(T));
+        }
+
+        if (DATA_TYPE) {
+            memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
+        } else {
+            for (int i = 0; i < fCount; ++i) {
+                new (fItemArray + i) T(array[i]);
+            }
+        }
+    }
+
+    /**
+     * Copy C array to SkTArray, using preallocated storage if preAllocCount >=
+     * preAllocCount. Otherwise preAllocStorage is only used if the array
+     * shrinks to fit.
+     */
+    SkTArray(const T* array, int count,
+             void* preAllocStorage, int preAllocCount) {
+
+        SkASSERT(count >= 0);
+        SkASSERT(preAllocCount >= 0);
+
+        // for same reason as non-copying cons we allow NULL, 0 for prealloc
+        SkASSERT((NULL == preAllocStorage) == !preAllocCount);
+
+        fCount              = count;
+        fReserveCount       = (preAllocCount > 0) ? preAllocCount :
+                                                    gMIN_ALLOC_COUNT;
+        fPreAllocMemArray   = preAllocStorage;
+
+        if (fReserveCount >= fCount && preAllocCount) {
+            fAllocCount = fReserveCount;
+            fMemArray = preAllocStorage;
+        } else {
+            fAllocCount = SkMax32(fCount, fReserveCount);
+            fMemArray = sk_malloc_throw(fAllocCount * sizeof(T));
+        }
+
+        if (DATA_TYPE) {
+            memcpy(fMemArray, array, sizeof(T) * fCount);
+        } else {
+            for (int i = 0; i < fCount; ++i) {
+                new (fItemArray + i) T(array[i]);
+            }
+        }
+    }
+
+    /**
+     * assign copy of array to this
+     */
+    SkTArray& operator =(const SkTArray& array) {
+        for (int i = 0; i < fCount; ++i) {
+            fItemArray[i].~T();
+        }
+        fCount = 0;
+        checkRealloc((int)array.count());
+        fCount = array.count();
+        if (DATA_TYPE) {
+            memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
+        } else {
+            for (int i = 0; i < fCount; ++i) {
+                new (fItemArray + i) T(array[i]);
+            }
+        }
+        return *this;
+    }
+
+    ~SkTArray() {
+        for (int i = 0; i < fCount; ++i) {
+            fItemArray[i].~T();
+        }
+        if (fMemArray != fPreAllocMemArray) {
+            sk_free(fMemArray);
+        }
+    }
+
+    /**
+     * Resets to count() == 0
+     */
+    void reset() { this->pop_back_n(fCount); }
+
+    /**
+     * Number of elements in the array.
+     */
+    int count() const { return fCount; }
+
+    /**
+     * Is the array empty.
+     */
+    bool empty() const { return !fCount; }
+
+    /**
+     * Adds 1 new default-constructed T value and returns in by reference. Note
+     * the reference only remains valid until the next call that adds or removes
+     * elements.
+     */
+    T& push_back() {
+        checkRealloc(1);
+        new ((char*)fMemArray+sizeof(T)*fCount) T;
+        ++fCount;
+        return fItemArray[fCount-1];
+    }
+
+    /**
+     * Allocates n more default T values, and returns the address of the start
+     * of that new range. Note: this address is only valid until the next API
+     * call made on the array that might add or remove elements.
+     */
+    T* push_back_n(int n) {
+        SkASSERT(n >= 0);
+        checkRealloc(n);
+        for (int i = 0; i < n; ++i) {
+            new (fItemArray + fCount + i) T;
+        }
+        fCount += n;
+        return fItemArray + fCount - n;
+    }
+
+    /**
+     * Removes the last element. Not safe to call when count() == 0.
+     */
+    void pop_back() {
+        SkASSERT(fCount > 0);
+        --fCount;
+        fItemArray[fCount].~T();
+        checkRealloc(0);
+    }
+
+    /**
+     * Removes the last n elements. Not safe to call when count() < n.
+     */
+    void pop_back_n(int n) {
+        SkASSERT(n >= 0);
+        SkASSERT(fCount >= n);
+        fCount -= n;
+        for (int i = 0; i < n; ++i) {
+            fItemArray[i].~T();
+        }
+        checkRealloc(0);
+    }
+
+    /**
+     * Pushes or pops from the back to resize. Pushes will be default
+     * initialized.
+     */
+    void resize_back(int newCount) {
+        SkASSERT(newCount >= 0);
+
+        if (newCount > fCount) {
+            push_back_n(newCount - fCount);
+        } else if (newCount < fCount) {
+            pop_back_n(fCount - newCount);
+        }
+    }
+
+    /**
+     * Get the i^th element.
+     */
+    T& operator[] (int i) {
+        SkASSERT(i < fCount);
+        SkASSERT(i >= 0);
+        return fItemArray[i];
+    }
+
+    const T& operator[] (int i) const {
+        SkASSERT(i < fCount);
+        SkASSERT(i >= 0);
+        return fItemArray[i];
+    }
+
+    /**
+     * equivalent to operator[](0)
+     */
+    T& front() { SkASSERT(fCount > 0); return fItemArray[0];}
+
+    const T& front() const { SkASSERT(fCount > 0); return fItemArray[0];}
+
+    /**
+     * equivalent to operator[](count() - 1)
+     */
+    T& back() { SkASSERT(fCount); return fItemArray[fCount - 1];}
+
+    const T& back() const { SkASSERT(fCount > 0); return fItemArray[fCount - 1];}
+
+    /**
+     * equivalent to operator[](count()-1-i)
+     */
+    T& fromBack(int i) {
+        SkASSERT(i >= 0);
+        SkASSERT(i < fCount);
+        return fItemArray[fCount - i - 1];
+    }
+
+    const T& fromBack(int i) const {
+        SkASSERT(i >= 0);
+        SkASSERT(i < fCount);
+        return fItemArray[fCount - i - 1];
+    }
+
+private:
+
+    static const int gMIN_ALLOC_COUNT = 8;
+
+    inline void checkRealloc(int delta) {
+        SkASSERT(fCount >= 0);
+        SkASSERT(fAllocCount >= 0);
+
+        SkASSERT(-delta <= fCount);
+
+        int newCount = fCount + delta;
+        int fNewAllocCount = fAllocCount;
+
+        if (newCount > fAllocCount) {
+            fNewAllocCount = SkMax32(newCount + ((newCount + 1) >> 1),
+                                   fReserveCount);
+        } else if (newCount < fAllocCount / 3) {
+            fNewAllocCount = SkMax32(fAllocCount / 2, fReserveCount);
+        }
+
+        if (fNewAllocCount != fAllocCount) {
+
+            fAllocCount = fNewAllocCount;
+            char* fNewMemArray;
+
+            if (fAllocCount == fReserveCount && NULL != fPreAllocMemArray) {
+                fNewMemArray = (char*) fPreAllocMemArray;
+            } else {
+                fNewMemArray = (char*) sk_malloc_throw(fAllocCount*sizeof(T));
+            }
+
+            if (DATA_TYPE) {
+                memcpy(fNewMemArray, fMemArray, fCount * sizeof(T));
+            } else {
+                for (int i = 0; i < fCount; ++i) {
+                    new (fNewMemArray + sizeof(T) * i) T(fItemArray[i]);
+                    fItemArray[i].~T();
+                }
+            }
+
+            if (fMemArray != fPreAllocMemArray) {
+                sk_free(fMemArray);
+            }
+            fMemArray = fNewMemArray;
+        }
+    }
+
+    int fReserveCount;
+    int fCount;
+    int fAllocCount;
+    void*    fPreAllocMemArray;
+    union {
+        T*       fItemArray;
+        void*    fMemArray;
+    };
+};
+
+#endif
+
diff --git a/include/core/SkTemplates.h b/include/core/SkTemplates.h
index 75a8b42..03f0892 100644
--- a/include/core/SkTemplates.h
+++ b/include/core/SkTemplates.h
@@ -262,5 +262,37 @@
     };
 };
 
+/**
+ * Reserves memory that is aligned on double and pointer boundaries.
+ * Hopefully this is sufficient for all practical purposes.
+ */
+template <size_t N> class SkAlignedSStorage : SkNoncopyable {
+public:
+    void* get() { return fData; }
+private:
+    union {
+        void*   fPtr;
+        double  fDouble;
+        char    fData[N];
+    };
+};
+
+/**
+ * Reserves memory that is aligned on double and pointer boundaries.
+ * Hopefully this is sufficient for all practical purposes. Otherwise,
+ * we have to do some arcane trickery to determine alignment of non-POD
+ * types. Lifetime of the memory is the lifetime of the object.
+ */
+template <int N, typename T> class SkAlignedSTStorage : SkNoncopyable {
+public:
+    /**
+     * Returns void* because this object does not initialize the
+     * memory. Use placement new for types that require a cons.
+     */
+    void* get() { return fStorage.get(); }
+private:
+    SkAlignedSStorage<sizeof(T)*N> fStorage;
+};
+
 #endif