Refactor dictionaries for use by entities other than just SkPicture
Review URL: https://codereview.appspot.com/6101043
git-svn-id: http://skia.googlecode.com/svn/trunk@4077 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/core/SkOrderedWriteBuffer.h b/include/core/SkOrderedWriteBuffer.h
index 51daf5c..947877b 100644
--- a/include/core/SkOrderedWriteBuffer.h
+++ b/include/core/SkOrderedWriteBuffer.h
@@ -22,6 +22,8 @@
size_t storageSize);
virtual ~SkOrderedWriteBuffer() {}
+ 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); }
diff --git a/src/core/SkPictureFlat.cpp b/src/core/SkPictureFlat.cpp
index 68a6651..edbf4e3 100644
--- a/src/core/SkPictureFlat.cpp
+++ b/src/core/SkPictureFlat.cpp
@@ -14,216 +14,7 @@
#include "SkShader.h"
#include "SkTypeface.h"
#include "SkXfermode.h"
-#include "SkOrderedReadBuffer.h"
-#include "SkOrderedWriteBuffer.h"
-SkFlatData* SkFlatData::Alloc(SkChunkAlloc* heap, int32_t size, int index) {
- SkFlatData* result = (SkFlatData*) heap->allocThrow(size + sizeof(SkFlatData));
- result->fIndex = index;
- result->fAllocSize = size + sizeof(result->fAllocSize);
- return result;
-}
-
-SkFlatBitmap* SkFlatBitmap::Flatten(SkChunkAlloc* heap, const SkBitmap& bitmap,
- int index, SkRefCntSet* rec) {
- SkOrderedWriteBuffer buffer(1024);
- buffer.setRefCntRecorder(rec);
-
- bitmap.flatten(buffer);
- size_t size = buffer.size();
- SkFlatBitmap* result = (SkFlatBitmap*) INHERITED::Alloc(heap, size, index);
- buffer.flatten(result->fBitmapData);
- return result;
-}
-
-SkFlatMatrix* SkFlatMatrix::Flatten(SkChunkAlloc* heap, const SkMatrix& matrix, int index) {
- size_t size = matrix.flatten(NULL);
- SkFlatMatrix* result = (SkFlatMatrix*) INHERITED::Alloc(heap, size, index);
- matrix.flatten(&result->fMatrixData);
- return result;
-}
-
-#ifdef SK_DEBUG_DUMP
-void SkFlatMatrix::dump() const {
- const SkMatrix* matrix = (const SkMatrix*) fMatrixData;
- char pBuffer[DUMP_BUFFER_SIZE];
- char* bufferPtr = pBuffer;
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "matrix: ");
- SkScalar scaleX = matrix->getScaleX();
- SkMatrix defaultMatrix;
- defaultMatrix.reset();
- if (scaleX != defaultMatrix.getScaleX())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "scaleX:%g ", SkScalarToFloat(scaleX));
- SkScalar scaleY = matrix->getScaleY();
- if (scaleY != defaultMatrix.getScaleY())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "scaleY:%g ", SkScalarToFloat(scaleY));
- SkScalar skewX = matrix->getSkewX();
- if (skewX != defaultMatrix.getSkewX())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "skewX:%g ", SkScalarToFloat(skewX));
- SkScalar skewY = matrix->getSkewY();
- if (skewY != defaultMatrix.getSkewY())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "skewY:%g ", SkScalarToFloat(skewY));
- SkScalar translateX = matrix->getTranslateX();
- if (translateX != defaultMatrix.getTranslateX())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "translateX:%g ", SkScalarToFloat(translateX));
- SkScalar translateY = matrix->getTranslateY();
- if (translateY != defaultMatrix.getTranslateY())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "translateY:%g ", SkScalarToFloat(translateY));
- SkScalar perspX = matrix->getPerspX();
- if (perspX != defaultMatrix.getPerspX())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "perspX:%g ", SkFractToFloat(perspX));
- SkScalar perspY = matrix->getPerspY();
- if (perspY != defaultMatrix.getPerspY())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "perspY:%g ", SkFractToFloat(perspY));
- SkDebugf("%s\n", pBuffer);
-}
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-
-SkFlatPaint* SkFlatPaint::Flatten(SkChunkAlloc* heap, const SkPaint& paint,
- int index, SkRefCntSet* rec,
- SkRefCntSet* faceRecorder) {
- intptr_t storage[256];
- SkOrderedWriteBuffer buffer(4*sizeof(SkPaint), storage, sizeof(storage));
-
- buffer.setRefCntRecorder(rec);
- buffer.setTypefaceRecorder(faceRecorder);
-
- paint.flatten(buffer);
- uint32_t size = buffer.size();
- SkFlatPaint* result = (SkFlatPaint*) INHERITED::Alloc(heap, size, index);
- buffer.flatten(&result->fPaintData);
- return result;
-}
-
-void SkFlatPaint::Read(const void* storage, SkPaint* paint,
- SkRefCntPlayback* rcp, SkTypefacePlayback* facePlayback) {
- SkOrderedReadBuffer buffer(storage, 1024*1024);
- if (rcp) {
- rcp->setupBuffer(buffer);
- }
- if (facePlayback) {
- facePlayback->setupBuffer(buffer);
- }
- paint->unflatten(buffer);
-}
-
-#ifdef SK_DEBUG_DUMP
-void SkFlatPaint::dump() const {
- SkPaint defaultPaint;
- SkFlattenableReadBuffer buffer(fPaintData);
- SkTypeface* typeface = (SkTypeface*) buffer.readPtr();
- char pBuffer[DUMP_BUFFER_SIZE];
- char* bufferPtr = pBuffer;
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "paint: ");
- if (typeface != defaultPaint.getTypeface())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "typeface:%p ", typeface);
- SkScalar textSize = buffer.readScalar();
- if (textSize != defaultPaint.getTextSize())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "textSize:%g ", SkScalarToFloat(textSize));
- SkScalar textScaleX = buffer.readScalar();
- if (textScaleX != defaultPaint.getTextScaleX())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "textScaleX:%g ", SkScalarToFloat(textScaleX));
- SkScalar textSkewX = buffer.readScalar();
- if (textSkewX != defaultPaint.getTextSkewX())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "textSkewX:%g ", SkScalarToFloat(textSkewX));
- const SkPathEffect* pathEffect = (const SkPathEffect*) buffer.readFlattenable();
- if (pathEffect != defaultPaint.getPathEffect())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "pathEffect:%p ", pathEffect);
- SkDELETE(pathEffect);
- const SkShader* shader = (const SkShader*) buffer.readFlattenable();
- if (shader != defaultPaint.getShader())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "shader:%p ", shader);
- SkDELETE(shader);
- const SkXfermode* xfermode = (const SkXfermode*) buffer.readFlattenable();
- if (xfermode != defaultPaint.getXfermode())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "xfermode:%p ", xfermode);
- SkDELETE(xfermode);
- const SkMaskFilter* maskFilter = (const SkMaskFilter*) buffer.readFlattenable();
- if (maskFilter != defaultPaint.getMaskFilter())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "maskFilter:%p ", maskFilter);
- SkDELETE(maskFilter);
- const SkColorFilter* colorFilter = (const SkColorFilter*) buffer.readFlattenable();
- if (colorFilter != defaultPaint.getColorFilter())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "colorFilter:%p ", colorFilter);
- SkDELETE(colorFilter);
- const SkRasterizer* rasterizer = (const SkRasterizer*) buffer.readFlattenable();
- if (rasterizer != defaultPaint.getRasterizer())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "rasterizer:%p ", rasterizer);
- SkDELETE(rasterizer);
- const SkDrawLooper* drawLooper = (const SkDrawLooper*) buffer.readFlattenable();
- if (drawLooper != defaultPaint.getLooper())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "drawLooper:%p ", drawLooper);
- SkDELETE(drawLooper);
- unsigned color = buffer.readU32();
- if (color != defaultPaint.getColor())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "color:0x%x ", color);
- SkScalar strokeWidth = buffer.readScalar();
- if (strokeWidth != defaultPaint.getStrokeWidth())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "strokeWidth:%g ", SkScalarToFloat(strokeWidth));
- SkScalar strokeMiter = buffer.readScalar();
- if (strokeMiter != defaultPaint.getStrokeMiter())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "strokeMiter:%g ", SkScalarToFloat(strokeMiter));
- unsigned flags = buffer.readU16();
- if (flags != defaultPaint.getFlags())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "flags:0x%x ", flags);
- int align = buffer.readU8();
- if (align != defaultPaint.getTextAlign())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "align:0x%x ", align);
- int strokeCap = buffer.readU8();
- if (strokeCap != defaultPaint.getStrokeCap())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "strokeCap:0x%x ", strokeCap);
- int strokeJoin = buffer.readU8();
- if (strokeJoin != defaultPaint.getStrokeJoin())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "align:0x%x ", strokeJoin);
- int style = buffer.readU8();
- if (style != defaultPaint.getStyle())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "style:0x%x ", style);
- int textEncoding = buffer.readU8();
- if (textEncoding != defaultPaint.getTextEncoding())
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "textEncoding:0x%x ", textEncoding);
- SkDebugf("%s\n", pBuffer);
-}
-#endif
-
-SkFlatRegion* SkFlatRegion::Flatten(SkChunkAlloc* heap, const SkRegion& region, int index) {
- uint32_t size = region.flatten(NULL);
- SkFlatRegion* result = (SkFlatRegion*) INHERITED::Alloc(heap, size, index);
- region.flatten(&result->fRegionData);
- return result;
-}
-
///////////////////////////////////////////////////////////////////////////////
SkRefCntPlayback::SkRefCntPlayback() : fCount(0), fArray(NULL) {}
@@ -266,3 +57,49 @@
return obj;
}
+///////////////////////////////////////////////////////////////////////////////
+
+SkFlatData* SkFlatData::Create(SkChunkAlloc* heap, const void* obj,
+ int index, void (*flattenProc)(SkOrderedWriteBuffer&, const void*),
+ SkRefCntSet* refCntRecorder, SkRefCntSet* faceRecorder) {
+
+ // a buffer of 256 bytes should be sufficient for most paints, regions,
+ // and matrices.
+ intptr_t storage[256];
+ SkOrderedWriteBuffer buffer(256, storage, sizeof(storage));
+ if (refCntRecorder) {
+ buffer.setRefCntRecorder(refCntRecorder);
+ }
+ if (faceRecorder) {
+ buffer.setTypefaceRecorder(faceRecorder);
+ }
+
+ flattenProc(buffer, obj);
+ uint32_t size = buffer.size();
+
+ // allocate the enough memory to hold both SkFlatData and the serialized
+ // contents
+ SkFlatData* result = (SkFlatData*) heap->allocThrow(size + sizeof(SkFlatData));
+ result->fIndex = index;
+ result->fAllocSize = size;
+
+ // put the serialized contents into the data section of the new allocation
+ buffer.flatten(result->data());
+ return result;
+}
+
+void SkFlatData::unflatten(void* result,
+ void (*unflattenProc)(SkOrderedReadBuffer&, void*),
+ SkRefCntPlayback* refCntPlayback,
+ SkTypefacePlayback* facePlayback) const {
+
+ SkOrderedReadBuffer buffer(this->data(), fAllocSize);
+ if (refCntPlayback) {
+ refCntPlayback->setupBuffer(buffer);
+ }
+ if (facePlayback) {
+ facePlayback->setupBuffer(buffer);
+ }
+ unflattenProc(buffer, result);
+ SkASSERT(fAllocSize == (int32_t)buffer.offset());
+}
diff --git a/src/core/SkPictureFlat.h b/src/core/SkPictureFlat.h
index 10432c2..e0a5b4f 100644
--- a/src/core/SkPictureFlat.h
+++ b/src/core/SkPictureFlat.h
@@ -11,11 +11,13 @@
#include "SkChunkAlloc.h"
#include "SkBitmap.h"
#include "SkOrderedReadBuffer.h"
+#include "SkOrderedWriteBuffer.h"
#include "SkPicture.h"
#include "SkMatrix.h"
#include "SkPaint.h"
#include "SkPath.h"
#include "SkRegion.h"
+#include "SkTSearch.h"
enum DrawType {
UNUSED,
@@ -127,112 +129,193 @@
SkFlattenable::Factory* fArray;
};
+///////////////////////////////////////////////////////////////////////////////
+//
+//
+// The following templated classes provide an efficient way to store and compare
+// objects that have been flattened (i.e. serialized in an ordered binary
+// format).
+//
+// SkFlatData: is a simple indexable container for the flattened data
+// which is agnostic to the type of data is is indexing. It is
+// also responsible for flattening/unflattening objects but
+// details of that operation are hidden in the provided procs
+// SkFlatDictionary: is a abstract templated dictionary that maintains a
+// searchable set of SkFlataData objects of type T.
+//
+// NOTE: any class that wishes to be used in conjunction with SkFlatDictionary
+// must subclass the dictionary and provide the necessary flattening procs.
+// The end of this header contains dictionary subclasses for some common classes
+// like SkBitmap, SkMatrix, SkPaint, and SkRegion.
+//
+//
+///////////////////////////////////////////////////////////////////////////////
+
class SkFlatData {
public:
+
static int Compare(const SkFlatData* a, const SkFlatData* b) {
- return memcmp(&a->fAllocSize, &b->fAllocSize, a->fAllocSize);
+ return memcmp(a->data(), b->data(), a->fAllocSize);
}
int index() const { return fIndex; }
+ void* data() const { return (char*)this + sizeof(*this); }
#ifdef SK_DEBUG_SIZE
- size_t size() const { return sizeof(fIndex) + fAllocSize; }
+ size_t size() const { return sizeof(SkFlatData) + fAllocSize; }
#endif
-protected:
- static SkFlatData* Alloc(SkChunkAlloc* heap, int32_t size, int index);
-
+ static SkFlatData* Create(SkChunkAlloc* heap, const void* obj, int index,
+ void (*flattenProc)(SkOrderedWriteBuffer&, const void*),
+ SkRefCntSet* refCntRecorder = NULL,
+ SkRefCntSet* faceRecorder = NULL);
+ void unflatten(void* result,
+ void (*unflattenProc)(SkOrderedReadBuffer&, void*),
+ SkRefCntPlayback* refCntPlayback = NULL,
+ SkTypefacePlayback* facePlayback = NULL) const;
+
+private:
int fIndex;
int32_t fAllocSize;
};
-class SkFlatBitmap : public SkFlatData {
+template <class T>
+class SkFlatDictionary {
public:
- static SkFlatBitmap* Flatten(SkChunkAlloc*, const SkBitmap&, int index,
- SkRefCntSet*);
+ SkFlatDictionary(SkChunkAlloc* heap) {
+ fFlattenProc = NULL;
+ fUnflattenProc = NULL;
+ fHeap = heap;
+ // set to 1 since returning a zero from find() indicates failure
+ fNextIndex = 1;
+ }
- void unflatten(SkBitmap* bitmap, SkRefCntPlayback* rcp) const {
- SkOrderedReadBuffer buffer(fBitmapData, fAllocSize);
- if (rcp) {
- rcp->setupBuffer(buffer);
+ int count() const { return fData.count(); }
+
+ const SkFlatData* operator[](int index) const {
+ SkASSERT(index >= 0 && index < fData.count());
+ return fData[index];
+ }
+
+ /**
+ * Clears the dictionary of all entries. However, it does NOT free the
+ * memory that was allocated for each entry.
+ */
+ void reset() { fData.reset(); fNextIndex = 1; }
+
+ /**
+ * Given an element of type T it returns its index in the dictionary. If
+ * the element wasn't previously in the dictionary it is automatically added
+ */
+ int find(const T* element, SkRefCntSet* refCntRecorder = NULL,
+ SkRefCntSet* faceRecorder = NULL) {
+ if (element == NULL)
+ return 0;
+ SkFlatData* flat = SkFlatData::Create(fHeap, element, fNextIndex,
+ fFlattenProc, refCntRecorder, faceRecorder);
+ int index = SkTSearch<SkFlatData>((const SkFlatData**) fData.begin(),
+ fData.count(), flat, sizeof(flat), &SkFlatData::Compare);
+ if (index >= 0) {
+ (void)fHeap->unalloc(flat);
+ return fData[index]->index();
}
- bitmap->unflatten(buffer);
+ index = ~index;
+ *fData.insert(index) = flat;
+ SkASSERT(fData.count() == fNextIndex);
+ return fNextIndex++;
}
-#ifdef SK_DEBUG_VALIDATE
- void validate() const {
- // to be written
+ /**
+ * Given a pointer to a array of type T we allocate the array and fill it
+ * with the unflattened dictionary contents. The return value is the size of
+ * the allocated array.
+ */
+ int unflattenDictionary(T*& array, SkRefCntPlayback* refCntPlayback = NULL,
+ SkTypefacePlayback* facePlayback = NULL) const {
+ int elementCount = fData.count();
+ if (elementCount > 0) {
+ array = SkNEW_ARRAY(T, elementCount);
+ for (const SkFlatData** elementPtr = fData.begin();
+ elementPtr != fData.end(); elementPtr++) {
+ const SkFlatData* element = *elementPtr;
+ int index = element->index() - 1;
+ element->unflatten(&array[index], fUnflattenProc,
+ refCntPlayback, facePlayback);
+ }
+ }
+ return elementCount;
}
-#endif
+
+protected:
+ void (*fFlattenProc)(SkOrderedWriteBuffer&, const void*);
+ void (*fUnflattenProc)(SkOrderedReadBuffer&, void*);
private:
- char fBitmapData[1];
- typedef SkFlatData INHERITED;
+ SkChunkAlloc* fHeap;
+ int fNextIndex;
+ SkTDArray<const SkFlatData*> fData;
};
-class SkFlatMatrix : public SkFlatData {
+///////////////////////////////////////////////////////////////////////////////
+// Some common dictionaries are defined here for both reference and convenience
+///////////////////////////////////////////////////////////////////////////////
+
+template <class T>
+static void SkFlattenObjectProc(SkOrderedWriteBuffer& buffer, const void* obj) {
+ ((T*)obj)->flatten(buffer);
+}
+
+template <class T>
+static void SkUnflattenObjectProc(SkOrderedReadBuffer& buffer, void* obj) {
+ ((T*)obj)->unflatten(buffer);
+}
+
+class SkBitmapDictionary : public SkFlatDictionary<SkBitmap> {
public:
- static SkFlatMatrix* Flatten(SkChunkAlloc* heap, const SkMatrix& matrix, int index);
-
- void unflatten(SkMatrix* result) const {
- result->unflatten(fMatrixData);
+ SkBitmapDictionary(SkChunkAlloc* heap) : SkFlatDictionary<SkBitmap>(heap) {
+ fFlattenProc = &SkFlattenObjectProc<SkBitmap>;
+ fUnflattenProc = &SkUnflattenObjectProc<SkBitmap>;
}
-
-#ifdef SK_DEBUG_DUMP
- void dump() const;
-#endif
-
-#ifdef SK_DEBUG_VALIDATE
- void validate() const {
- // to be written
- }
-#endif
-
-private:
- char fMatrixData[1];
- typedef SkFlatData INHERITED;
};
-class SkFlatPaint : public SkFlatData {
-public:
- static SkFlatPaint* Flatten(SkChunkAlloc* heap, const SkPaint& paint,
- int index, SkRefCntSet*,
- SkRefCntSet* faceRecorder);
-
- void unflatten(SkPaint* result, SkRefCntPlayback* rcp,
- SkTypefacePlayback* facePlayback) const {
- Read(fPaintData, result, rcp, facePlayback);
+class SkMatrixDictionary : public SkFlatDictionary<SkMatrix> {
+ public:
+ SkMatrixDictionary(SkChunkAlloc* heap) : SkFlatDictionary<SkMatrix>(heap) {
+ fFlattenProc = &flattenMatrix;
+ fUnflattenProc = &unflattenMatrix;
}
-
- static void Read(const void* storage, SkPaint* paint, SkRefCntPlayback*,
- SkTypefacePlayback* facePlayback);
-#ifdef SK_DEBUG_DUMP
- void dump() const;
-#endif
-
-private:
- char fPaintData[1];
- typedef SkFlatData INHERITED;
+ static void flattenMatrix(SkOrderedWriteBuffer& buffer, const void* obj) {
+ buffer.getWriter32()->writeMatrix(*(SkMatrix*)obj);
+ }
+
+ static void unflattenMatrix(SkOrderedReadBuffer& buffer, void* obj) {
+ buffer.getReader32()->readMatrix((SkMatrix*)obj);
+ }
};
-class SkFlatRegion : public SkFlatData {
-public:
- static SkFlatRegion* Flatten(SkChunkAlloc* heap, const SkRegion& region, int index);
-
- void unflatten(SkRegion* result) const {
- result->unflatten(fRegionData);
+class SkPaintDictionary : public SkFlatDictionary<SkPaint> {
+ public:
+ SkPaintDictionary(SkChunkAlloc* heap) : SkFlatDictionary<SkPaint>(heap) {
+ fFlattenProc = &SkFlattenObjectProc<SkPaint>;
+ fUnflattenProc = &SkUnflattenObjectProc<SkPaint>;
+ }
+};
+
+class SkRegionDictionary : public SkFlatDictionary<SkRegion> {
+ public:
+ SkRegionDictionary(SkChunkAlloc* heap) : SkFlatDictionary<SkRegion>(heap) {
+ fFlattenProc = &flattenRegion;
+ fUnflattenProc = &unflattenRegion;
}
-#ifdef SK_DEBUG_VALIDATE
- void validate() const {
- // to be written
+ static void flattenRegion(SkOrderedWriteBuffer& buffer, const void* obj) {
+ buffer.getWriter32()->writeRegion(*(SkRegion*)obj);
}
-#endif
-private:
- char fRegionData[1];
- typedef SkFlatData INHERITED;
+ static void unflattenRegion(SkOrderedReadBuffer& buffer, void* obj) {
+ buffer.getReader32()->readRegion((SkRegion*)obj);
+ }
};
#endif
diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp
index b3eb147..d2cf4db 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -77,41 +77,15 @@
fRCPlayback.reset(&record.fRCSet);
fTFPlayback.reset(&record.fTFSet);
- const SkTDArray<const SkFlatBitmap* >& bitmaps = record.getBitmaps();
- fBitmapCount = bitmaps.count();
- if (fBitmapCount > 0) {
- fBitmaps = SkNEW_ARRAY(SkBitmap, fBitmapCount);
- for (const SkFlatBitmap** flatBitmapPtr = bitmaps.begin();
- flatBitmapPtr != bitmaps.end(); flatBitmapPtr++) {
- const SkFlatBitmap* flatBitmap = *flatBitmapPtr;
- int index = flatBitmap->index() - 1;
- flatBitmap->unflatten(&fBitmaps[index], &fRCPlayback);
- }
- }
+ fBitmapCount = record.getBitmaps().unflattenDictionary(fBitmaps, &fRCPlayback);
+ fMatrixCount = record.getMatrices().unflattenDictionary(fMatrices);
+ fPaintCount = record.getPaints().unflattenDictionary(fPaints, &fRCPlayback, &fTFPlayback);
+ fRegionCount = record.getRegions().unflattenDictionary(fRegions);
- const SkTDArray<const SkFlatMatrix* >& matrices = record.getMatrices();
- fMatrixCount = matrices.count();
- if (fMatrixCount > 0) {
- fMatrices = SkNEW_ARRAY(SkMatrix, fMatrixCount);
- for (const SkFlatMatrix** matrixPtr = matrices.begin();
- matrixPtr != matrices.end(); matrixPtr++) {
- const SkFlatMatrix* flatMatrix = *matrixPtr;
- flatMatrix->unflatten(&fMatrices[flatMatrix->index() - 1]);
- }
- }
-
- const SkTDArray<const SkFlatPaint* >& paints = record.getPaints();
- fPaintCount = paints.count();
- if (fPaintCount > 0) {
- fPaints = SkNEW_ARRAY(SkPaint, fPaintCount);
- for (const SkFlatPaint** flatPaintPtr = paints.begin();
- flatPaintPtr != paints.end(); flatPaintPtr++) {
- const SkFlatPaint* flatPaint = *flatPaintPtr;
- int index = flatPaint->index() - 1;
- SkASSERT((unsigned)index < (unsigned)fPaintCount);
- flatPaint->unflatten(&fPaints[index], &fRCPlayback, &fTFPlayback);
- }
- }
+ SkASSERT(fBitmapCount == record.getBitmaps().count());
+ SkASSERT(fMatrixCount == record.getMatrices().count());
+ SkASSERT(fPaintCount == record.getPaints().count());
+ SkASSERT(fRegionCount == record.getRegions().count());
fPathHeap = record.fPathHeap;
SkSafeRef(fPathHeap);
@@ -126,17 +100,6 @@
}
}
- const SkTDArray<const SkFlatRegion* >& regions = record.getRegions();
- fRegionCount = regions.count();
- if (fRegionCount > 0) {
- fRegions = SkNEW_ARRAY(SkRegion, fRegionCount);
- for (const SkFlatRegion** flatRegionPtr = regions.begin();
- flatRegionPtr != regions.end(); flatRegionPtr++) {
- const SkFlatRegion* flatRegion = *flatRegionPtr;
- flatRegion->unflatten(&fRegions[flatRegion->index() - 1]);
- }
- }
-
#ifdef SK_DEBUG_SIZE
int overall = fPlayback->size(&overallBytes);
bitmaps = fPlayback->bitmaps(&bitmapBytes);
@@ -349,11 +312,7 @@
writeTagSize(buffer, PICT_REGION_TAG, fRegionCount);
for (i = 0; i < fRegionCount; i++) {
- uint32_t size = fRegions[i].flatten(NULL);
- buffer.write32(size);
- SkAutoSMalloc<512> storage(size);
- fRegions[i].flatten(storage.get());
- buffer.writePad(storage.get(), size);
+ buffer.getWriter32()->writeRegion(fRegions[i]);
}
// now we can write to the stream again
@@ -460,10 +419,7 @@
fRegionCount = readTagSize(buffer, PICT_REGION_TAG);
fRegions = SkNEW_ARRAY(SkRegion, fRegionCount);
for (i = 0; i < fRegionCount; i++) {
- uint32_t bufferSize = buffer.readU32();
- SkDEBUGCODE(uint32_t bytes =)
- fRegions[i].unflatten(buffer.skip(bufferSize));
- SkASSERT(bufferSize == bytes);
+ buffer.getReader32()->readRegion(&fRegions[i]);
}
}
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index fdeec3f..422001b 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -12,8 +12,13 @@
#define HEAP_BLOCK_SIZE 4096
SkPictureRecord::SkPictureRecord(uint32_t flags) :
- fHeap(HEAP_BLOCK_SIZE), fWriter(MIN_WRITER_SIZE), fRecordFlags(flags) {
- fBitmapIndex = fMatrixIndex = fPaintIndex = fRegionIndex = 1;
+ fHeap(HEAP_BLOCK_SIZE),
+ fBitmaps(&fHeap),
+ fMatrices(&fHeap),
+ fPaints(&fHeap),
+ fRegions(&fHeap),
+ fWriter(MIN_WRITER_SIZE),
+ fRecordFlags(flags) {
#ifdef SK_DEBUG_SIZE
fPointBytes = fRectBytes = fTextBytes = 0;
fPointWrites = fRectWrites = fTextWrites = 0;
@@ -505,7 +510,7 @@
}
void SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
- addInt(find(fBitmaps, bitmap));
+ addInt(fBitmaps.find(&bitmap, &fRCSet));
}
void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
@@ -513,7 +518,7 @@
}
void SkPictureRecord::addMatrixPtr(const SkMatrix* matrix) {
- addInt(find(fMatrices, matrix));
+ addInt(fMatrices.find(matrix));
}
void SkPictureRecord::addPaint(const SkPaint& paint) {
@@ -521,7 +526,7 @@
}
void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
- addInt(find(fPaints, paint));
+ addInt(fPaints.find(paint, &fRCSet, &fTFSet));
}
void SkPictureRecord::addPath(const SkPath& path) {
@@ -589,7 +594,7 @@
}
void SkPictureRecord::addRegion(const SkRegion& region) {
- addInt(find(fRegions, region));
+ addInt(fRegions.find(®ion));
}
void SkPictureRecord::addText(const void* text, size_t byteLength) {
@@ -606,85 +611,6 @@
///////////////////////////////////////////////////////////////////////////////
-int SkPictureRecord::find(SkTDArray<const SkFlatBitmap* >& bitmaps, const SkBitmap& bitmap) {
- SkFlatBitmap* flat = SkFlatBitmap::Flatten(&fHeap, bitmap, fBitmapIndex,
- &fRCSet);
- int index = SkTSearch<SkFlatData>((const SkFlatData**) bitmaps.begin(),
- bitmaps.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
- if (index >= 0) {
- (void)fHeap.unalloc(flat);
- return bitmaps[index]->index();
- }
- index = ~index;
- *bitmaps.insert(index) = flat;
- return fBitmapIndex++;
-}
-
-int SkPictureRecord::find(SkTDArray<const SkFlatMatrix* >& matrices, const SkMatrix* matrix) {
- if (matrix == NULL)
- return 0;
- SkFlatMatrix* flat = SkFlatMatrix::Flatten(&fHeap, *matrix, fMatrixIndex);
- int index = SkTSearch<SkFlatData>((const SkFlatData**) matrices.begin(),
- matrices.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
- if (index >= 0) {
- (void)fHeap.unalloc(flat);
- return matrices[index]->index();
- }
- index = ~index;
- *matrices.insert(index) = flat;
- return fMatrixIndex++;
-}
-
-int SkPictureRecord::find(SkTDArray<const SkFlatPaint* >& paints, const SkPaint* paint) {
- if (paint == NULL) {
- return 0;
- }
-
- SkFlatPaint* flat = SkFlatPaint::Flatten(&fHeap, *paint, fPaintIndex,
- &fRCSet, &fTFSet);
- int index = SkTSearch<SkFlatData>((const SkFlatData**) paints.begin(),
- paints.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
- if (index >= 0) {
- (void)fHeap.unalloc(flat);
- return paints[index]->index();
- }
-
- index = ~index;
- *paints.insert(index) = flat;
- return fPaintIndex++;
-}
-
-int SkPictureRecord::find(SkTDArray<const SkFlatRegion* >& regions, const SkRegion& region) {
- SkFlatRegion* flat = SkFlatRegion::Flatten(&fHeap, region, fRegionIndex);
- int index = SkTSearch<SkFlatData>((const SkFlatData**) regions.begin(),
- regions.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
- if (index >= 0) {
- (void)fHeap.unalloc(flat);
- return regions[index]->index();
- }
- index = ~index;
- *regions.insert(index) = flat;
- return fRegionIndex++;
-}
-
-#ifdef SK_DEBUG_DUMP
-void SkPictureRecord::dumpMatrices() {
- int count = fMatrices.count();
- SkMatrix defaultMatrix;
- defaultMatrix.reset();
- for (int index = 0; index < count; index++) {
- const SkFlatMatrix* flatMatrix = fMatrices[index];
- flatMatrix->dump();
- }
-}
-
-void SkPictureRecord::dumpPaints() {
- int count = fPaints.count();
- for (int index = 0; index < count; index++)
- fPaints[index]->dump();
-}
-#endif
-
#ifdef SK_DEBUG_SIZE
size_t SkPictureRecord::size() const {
size_t result = 0;
diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h
index dfddffe..96809bf 100644
--- a/src/core/SkPictureRecord.h
+++ b/src/core/SkPictureRecord.h
@@ -69,19 +69,19 @@
void addFontMetricsTopBottom(const SkPaint& paint, SkScalar minY, SkScalar maxY);
- const SkTDArray<const SkFlatBitmap* >& getBitmaps() const {
+ const SkBitmapDictionary& getBitmaps() const {
return fBitmaps;
}
- const SkTDArray<const SkFlatMatrix* >& getMatrices() const {
+ const SkMatrixDictionary& getMatrices() const {
return fMatrices;
}
- const SkTDArray<const SkFlatPaint* >& getPaints() const {
+ const SkPaintDictionary& getPaints() const {
return fPaints;
}
const SkTDArray<SkPicture* >& getPictureRefs() const {
return fPictureRefs;
}
- const SkTDArray<const SkFlatRegion* >& getRegions() const {
+ const SkRegionDictionary& getRegions() const {
return fRegions;
}
@@ -127,13 +127,6 @@
void addRegion(const SkRegion& region);
void addText(const void* text, size_t byteLength);
- int find(SkTDArray<const SkFlatBitmap* >& bitmaps,
- const SkBitmap& bitmap);
- int find(SkTDArray<const SkFlatMatrix* >& matrices,
- const SkMatrix* matrix);
- int find(SkTDArray<const SkFlatPaint* >& paints, const SkPaint* paint);
- int find(SkTDArray<const SkFlatRegion* >& regions, const SkRegion& region);
-
#ifdef SK_DEBUG_DUMP
public:
void dumpMatrices();
@@ -170,14 +163,11 @@
private:
SkChunkAlloc fHeap;
- int fBitmapIndex;
- SkTDArray<const SkFlatBitmap* > fBitmaps;
- int fMatrixIndex;
- SkTDArray<const SkFlatMatrix* > fMatrices;
- int fPaintIndex;
- SkTDArray<const SkFlatPaint* > fPaints;
- int fRegionIndex;
- SkTDArray<const SkFlatRegion* > fRegions;
+ SkBitmapDictionary fBitmaps;
+ SkMatrixDictionary fMatrices;
+ SkPaintDictionary fPaints;
+ SkRegionDictionary fRegions;
+
SkPathHeap* fPathHeap; // reference counted
SkWriter32 fWriter;
diff --git a/src/effects/Sk2DPathEffect.cpp b/src/effects/Sk2DPathEffect.cpp
index 3f8c998..e19cdeb 100644
--- a/src/effects/Sk2DPathEffect.cpp
+++ b/src/effects/Sk2DPathEffect.cpp
@@ -74,18 +74,11 @@
void Sk2DPathEffect::flatten(SkFlattenableWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
- char storage[SkMatrix::kMaxFlattenSize];
- uint32_t size = fMatrix.flatten(storage);
- buffer.write32(size);
- buffer.write(storage, size);
+ buffer.writeMatrix(fMatrix);
}
Sk2DPathEffect::Sk2DPathEffect(SkFlattenableReadBuffer& buffer) {
- char storage[SkMatrix::kMaxFlattenSize];
- uint32_t size = buffer.readS32();
- SkASSERT(size <= sizeof(storage));
- buffer.read(storage, size);
- fMatrix.unflatten(storage);
+ buffer.readMatrix(&fMatrix);
fMatrixIsInvertible = fMatrix.invert(&fInverse);
}
diff --git a/src/effects/SkGroupShape.cpp b/src/effects/SkGroupShape.cpp
index 83a2043..8ec87c4 100644
--- a/src/effects/SkGroupShape.cpp
+++ b/src/effects/SkGroupShape.cpp
@@ -92,13 +92,9 @@
const Rec* stop = fList.end();
while (rec < stop) {
buffer.writeFlattenable(rec->fShape);
+ buffer.writeBool(rec->fMatrixRef);
if (rec->fMatrixRef) {
- char storage[SkMatrix::kMaxFlattenSize];
- uint32_t size = rec->fMatrixRef->flatten(storage);
- buffer.write32(size);
- buffer.writePad(storage, size);
- } else {
- buffer.write32(0);
+ buffer.writeMatrix(*rec->fMatrixRef);
}
rec += 1;
}
@@ -109,12 +105,10 @@
for (int i = 0; i < count; i++) {
SkShape* shape = reinterpret_cast<SkShape*>(buffer.readFlattenable());
SkMatrixRef* mr = NULL;
- uint32_t size = buffer.readS32();
- if (size) {
- char storage[SkMatrix::kMaxFlattenSize];
- buffer.read(storage, SkAlign4(size));
+ bool hasMatrix = buffer.readBool();
+ if (hasMatrix) {
mr = SkNEW(SkMatrixRef);
- mr->unflatten(storage);
+ buffer.readMatrix(mr);
}
if (shape) {
this->appendShape(shape, mr)->unref();
diff --git a/tests/CanvasTest.cpp b/tests/CanvasTest.cpp
index 3efbdea..814386e 100644
--- a/tests/CanvasTest.cpp
+++ b/tests/CanvasTest.cpp
@@ -583,14 +583,14 @@
// Verify that deserialization-serialization round trip conserves all
// data by comparing referenceRecord to roundTripRecord
- REPORTER_ASSERT_MESSAGE(reporter, referenceRecord->fBitmapIndex ==
- roundTripRecord->fBitmapIndex, testStep->assertMessage());
- REPORTER_ASSERT_MESSAGE(reporter, referenceRecord->fMatrixIndex ==
- roundTripRecord->fMatrixIndex, testStep->assertMessage());
- REPORTER_ASSERT_MESSAGE(reporter, referenceRecord->fPaintIndex ==
- roundTripRecord->fPaintIndex, testStep->assertMessage());
- REPORTER_ASSERT_MESSAGE(reporter, referenceRecord->fRegionIndex ==
- roundTripRecord->fRegionIndex, testStep->assertMessage());
+ REPORTER_ASSERT_MESSAGE(reporter, referenceRecord->fBitmaps.count() ==
+ roundTripRecord->fBitmaps.count(), testStep->assertMessage());
+ REPORTER_ASSERT_MESSAGE(reporter, referenceRecord->fMatrices.count() ==
+ roundTripRecord->fMatrices.count(), testStep->assertMessage());
+ REPORTER_ASSERT_MESSAGE(reporter, referenceRecord->fPaints.count() ==
+ roundTripRecord->fPaints.count(), testStep->assertMessage());
+ REPORTER_ASSERT_MESSAGE(reporter, referenceRecord->fRegions.count() ==
+ roundTripRecord->fRegions.count(), testStep->assertMessage());
char referenceBuffer[kMaxPictureBufferSize];
SkMemoryWStream referenceStream(referenceBuffer,
kMaxPictureBufferSize);