summaryrefslogtreecommitdiffstats
path: root/skia/picture
diff options
context:
space:
mode:
authorinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-27 00:09:42 +0000
committerinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-27 00:09:42 +0000
commitae2c20f398933a9e86c387dcc465ec0f71065ffc (patch)
treede668b1411e2ee0b4e49b6d8f8b68183134ac990 /skia/picture
parent09911bf300f1a419907a9412154760efd0b7abc3 (diff)
downloadchromium_src-ae2c20f398933a9e86c387dcc465ec0f71065ffc.zip
chromium_src-ae2c20f398933a9e86c387dcc465ec0f71065ffc.tar.gz
chromium_src-ae2c20f398933a9e86c387dcc465ec0f71065ffc.tar.bz2
Add skia to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'skia/picture')
-rw-r--r--skia/picture/SkPictureFlat.cpp266
-rw-r--r--skia/picture/SkPictureFlat.h225
-rw-r--r--skia/picture/SkPicturePlayback.cpp1366
-rw-r--r--skia/picture/SkPicturePlayback.h166
-rw-r--r--skia/picture/SkPictureRecord.cpp688
-rw-r--r--skia/picture/SkPictureRecord.h182
6 files changed, 2893 insertions, 0 deletions
diff --git a/skia/picture/SkPictureFlat.cpp b/skia/picture/SkPictureFlat.cpp
new file mode 100644
index 0000000..ba7119e
--- /dev/null
+++ b/skia/picture/SkPictureFlat.cpp
@@ -0,0 +1,266 @@
+#include "SkPictureFlat.h"
+
+#include "SkColorFilter.h"
+#include "SkDrawLooper.h"
+#include "SkMaskFilter.h"
+#include "SkRasterizer.h"
+#include "SkShader.h"
+#include "SkTypeface.h"
+#include "SkXfermode.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, SkRefCntRecorder* rec) {
+ SkFlattenableWriteBuffer 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) {
+ int32_t size = sizeof(SkMatrix);
+ SkFlatMatrix* result = (SkFlatMatrix*) INHERITED::Alloc(heap, size, index);
+ memcpy(&result->fMatrixData, &matrix, sizeof(SkMatrix));
+ 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, SkRefCntRecorder* rec,
+ SkRefCntRecorder* faceRecorder) {
+ SkFlattenableWriteBuffer buffer(2*sizeof(SkPaint));
+ 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) {
+ SkFlattenableReadBuffer buffer(storage);
+ 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
+
+SkFlatPath* SkFlatPath::Flatten(SkChunkAlloc* heap, const SkPath& path, int index) {
+ SkFlattenableWriteBuffer buffer(1024);
+ path.flatten(buffer);
+ uint32_t size = buffer.size();
+ SkFlatPath* result = (SkFlatPath*) INHERITED::Alloc(heap, size, index);
+ buffer.flatten(&result->fPathData);
+ return result;
+}
+
+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) {}
+
+SkRefCntPlayback::~SkRefCntPlayback() {
+ this->reset(NULL);
+}
+
+void SkRefCntPlayback::reset(const SkRefCntRecorder* rec) {
+ for (int i = 0; i < fCount; i++) {
+ SkASSERT(fArray[i]);
+ fArray[i]->unref();
+ }
+ SkDELETE_ARRAY(fArray);
+
+ if (rec) {
+ fCount = rec->count();
+ fArray = SkNEW_ARRAY(SkRefCnt*, fCount);
+ rec->get(fArray);
+ for (int i = 0; i < fCount; i++) {
+ fArray[i]->ref();
+ }
+ } else {
+ fCount = 0;
+ fArray = NULL;
+ }
+}
+
+void SkRefCntPlayback::setCount(int count) {
+ this->reset(NULL);
+
+ fCount = count;
+ fArray = SkNEW_ARRAY(SkRefCnt*, count);
+ bzero(fArray, count * sizeof(SkRefCnt*));
+}
+
+SkRefCnt* SkRefCntPlayback::set(int index, SkRefCnt* obj) {
+ SkASSERT((unsigned)index < (unsigned)fCount);
+ SkRefCnt_SafeAssign(fArray[index], obj);
+ return obj;
+}
+
diff --git a/skia/picture/SkPictureFlat.h b/skia/picture/SkPictureFlat.h
new file mode 100644
index 0000000..b4ce899
--- /dev/null
+++ b/skia/picture/SkPictureFlat.h
@@ -0,0 +1,225 @@
+#ifndef SkPictureFlat_DEFINED
+#define SkPictureFlat_DEFINED
+
+#include "SkChunkAlloc.h"
+#include "SkBitmap.h"
+#include "SkPicture.h"
+#include "SkMatrix.h"
+#include "SkPaint.h"
+#include "SkPath.h"
+#include "SkRegion.h"
+
+enum DrawType {
+ UNUSED,
+ CLIP_PATH,
+ CLIP_REGION,
+ CLIP_RECT,
+ CONCAT,
+ DRAW_BITMAP,
+ DRAW_BITMAP_MATRIX,
+ DRAW_BITMAP_RECT,
+ DRAW_PAINT,
+ DRAW_PATH,
+ DRAW_PICTURE,
+ DRAW_POINTS,
+ DRAW_POS_TEXT,
+ DRAW_POS_TEXT_H,
+ DRAW_RECT_GENERAL,
+ DRAW_RECT_SIMPLE,
+ DRAW_SPRITE,
+ DRAW_TEXT,
+ DRAW_TEXT_ON_PATH,
+ DRAW_VERTICES,
+ RESTORE,
+ ROTATE,
+ SAVE,
+ SAVE_LAYER,
+ SCALE,
+ SKEW,
+ TRANSLATE
+};
+
+enum DrawVertexFlags {
+ DRAW_VERTICES_HAS_TEXS = 0x01,
+ DRAW_VERTICES_HAS_COLORS = 0x02,
+ DRAW_VERTICES_HAS_INDICES = 0x04
+};
+
+class SkRefCntPlayback {
+public:
+ SkRefCntPlayback();
+ ~SkRefCntPlayback();
+
+ int count() const { return fCount; }
+
+ void reset(const SkRefCntRecorder*);
+
+ void setCount(int count);
+ SkRefCnt* set(int index, SkRefCnt*);
+
+ virtual void setupBuffer(SkFlattenableReadBuffer& buffer) const {
+ buffer.setRefCntArray(fArray, fCount);
+ }
+
+protected:
+ int fCount;
+ SkRefCnt** fArray;
+};
+
+class SkTypefacePlayback : public SkRefCntPlayback {
+public:
+ virtual void setupBuffer(SkFlattenableReadBuffer& buffer) const {
+ buffer.setTypefaceArray((SkTypeface**)fArray, fCount);
+ }
+};
+
+class SkFactoryPlayback {
+public:
+ SkFactoryPlayback(int count) : fCount(count) {
+ fArray = SkNEW_ARRAY(SkFlattenable::Factory, count);
+ }
+
+ ~SkFactoryPlayback() {
+ SkDELETE_ARRAY(fArray);
+ }
+
+ SkFlattenable::Factory* base() const { return fArray; }
+
+ void setupBuffer(SkFlattenableReadBuffer& buffer) const {
+ buffer.setFactoryPlayback(fArray, fCount);
+ }
+
+private:
+ int fCount;
+ SkFlattenable::Factory* fArray;
+};
+
+class SkFlatData {
+public:
+ static int Compare(const SkFlatData* a, const SkFlatData* b) {
+ return memcmp(&a->fAllocSize, &b->fAllocSize, a->fAllocSize);
+ }
+
+ int index() const { return fIndex; }
+
+#ifdef SK_DEBUG_SIZE
+ size_t size() const { return sizeof(fIndex) + fAllocSize; }
+#endif
+
+protected:
+ static SkFlatData* Alloc(SkChunkAlloc* heap, int32_t size, int index);
+
+ int fIndex;
+ int32_t fAllocSize;
+};
+
+class SkFlatBitmap : public SkFlatData {
+public:
+ static SkFlatBitmap* Flatten(SkChunkAlloc*, const SkBitmap&, int index,
+ SkRefCntRecorder*);
+
+ void unflatten(SkBitmap* bitmap, SkRefCntPlayback* rcp) const {
+ SkFlattenableReadBuffer buffer(fBitmapData);
+ if (rcp) {
+ rcp->setupBuffer(buffer);
+ }
+ bitmap->unflatten(buffer);
+ }
+
+#ifdef SK_DEBUG_VALIDATE
+ void validate() const {
+ // to be written
+ }
+#endif
+
+private:
+ char fBitmapData[1];
+ typedef SkFlatData INHERITED;
+};
+
+class SkFlatMatrix : public SkFlatData {
+public:
+ static SkFlatMatrix* Flatten(SkChunkAlloc* heap, const SkMatrix& matrix, int index);
+
+ void unflatten(SkMatrix* result) const {
+ memcpy(result, fMatrixData, sizeof(SkMatrix));
+ }
+
+#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, SkRefCntRecorder*,
+ SkRefCntRecorder* faceRecorder);
+
+ void unflatten(SkPaint* result, SkRefCntPlayback* rcp,
+ SkTypefacePlayback* facePlayback) const {
+ Read(fPaintData, result, rcp, facePlayback);
+ }
+
+ 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;
+};
+
+class SkFlatPath : public SkFlatData {
+public:
+ static SkFlatPath* Flatten(SkChunkAlloc* heap, const SkPath& path, int index);
+
+ void unflatten(SkPath* path) const {
+ SkFlattenableReadBuffer buffer(fPathData);
+ path->unflatten(buffer);
+ }
+
+#ifdef SK_DEBUG_VALIDATE
+ void validate() const {
+ // to be written
+ }
+#endif
+
+private:
+ char fPathData[1];
+ typedef SkFlatData INHERITED;
+};
+
+class SkFlatRegion : public SkFlatData {
+public:
+ static SkFlatRegion* Flatten(SkChunkAlloc* heap, const SkRegion& region, int index);
+
+ void unflatten(SkRegion* result) const {
+ result->unflatten(fRegionData);
+ }
+
+#ifdef SK_DEBUG_VALIDATE
+ void validate() const {
+ // to be written
+ }
+#endif
+
+private:
+ char fRegionData[1];
+ typedef SkFlatData INHERITED;
+};
+
+#endif
diff --git a/skia/picture/SkPicturePlayback.cpp b/skia/picture/SkPicturePlayback.cpp
new file mode 100644
index 0000000..3bf162e
--- /dev/null
+++ b/skia/picture/SkPicturePlayback.cpp
@@ -0,0 +1,1366 @@
+#include "SkPicturePlayback.h"
+#include "SkPictureRecord.h"
+#include "SkTypeface.h"
+#include <new>
+
+SkPicturePlayback::SkPicturePlayback() {
+ this->init();
+}
+
+SkPicturePlayback::SkPicturePlayback(const SkPictureRecord& record) {
+#ifdef SK_DEBUG_SIZE
+ size_t overallBytes, bitmapBytes, matricesBytes,
+ paintBytes, pathBytes, pictureBytes, regionBytes;
+ int bitmaps = record.bitmaps(&bitmapBytes);
+ int matrices = record.matrices(&matricesBytes);
+ int paints = record.paints(&paintBytes);
+ int paths = record.paths(&pathBytes);
+ int pictures = record.pictures(&pictureBytes);
+ int regions = record.regions(&regionBytes);
+ SkDebugf("picture record mem used %zd (stream %zd) ", record.size(),
+ record.streamlen());
+ if (bitmaps != 0)
+ SkDebugf("bitmaps size %zd (bitmaps:%d) ", bitmapBytes, bitmaps);
+ if (matrices != 0)
+ SkDebugf("matrices size %zd (matrices:%d) ", matricesBytes, matrices);
+ if (paints != 0)
+ SkDebugf("paints size %zd (paints:%d) ", paintBytes, paints);
+ if (paths != 0)
+ SkDebugf("paths size %zd (paths:%d) ", pathBytes, paths);
+ if (pictures != 0)
+ SkDebugf("pictures size %zd (pictures:%d) ", pictureBytes, pictures);
+ if (regions != 0)
+ SkDebugf("regions size %zd (regions:%d) ", regionBytes, regions);
+ if (record.fPointWrites != 0)
+ SkDebugf("points size %zd (points:%d) ", record.fPointBytes, record.fPointWrites);
+ if (record.fRectWrites != 0)
+ SkDebugf("rects size %zd (rects:%d) ", record.fRectBytes, record.fRectWrites);
+ if (record.fTextWrites != 0)
+ SkDebugf("text size %zd (text strings:%d) ", record.fTextBytes, record.fTextWrites);
+
+ SkDebugf("\n");
+#endif
+#ifdef SK_DEBUG_DUMP
+ record.dumpMatrices();
+ record.dumpPaints();
+#endif
+
+ record.validate();
+ const SkWriter32& writer = record.writeStream();
+ init();
+ if (writer.size() == 0)
+ return;
+
+ {
+ size_t size = writer.size();
+ void* buffer = sk_malloc_throw(size);
+ writer.flatten(buffer);
+ fReader.setMemory(buffer, size); // fReader owns buffer now
+ }
+
+ // copy over the refcnt dictionary to our reader
+ //
+ fRCPlayback.reset(&record.fRCRecorder);
+ fRCPlayback.setupBuffer(fReader);
+
+ fTFPlayback.reset(&record.fTFRecorder);
+ fTFPlayback.setupBuffer(fReader);
+
+ 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);
+ }
+ }
+
+ 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);
+ }
+ }
+
+ const SkTDArray<const SkFlatPath* >& paths = record.getPaths();
+ fPathCount = paths.count();
+ if (fPathCount > 0) {
+ fPaths = SkNEW_ARRAY(SkPath, fPathCount);
+ for (const SkFlatPath** flatPathPtr = paths.begin();
+ flatPathPtr != paths.end(); flatPathPtr++) {
+ const SkFlatPath* flatPath = *flatPathPtr;
+ flatPath->unflatten(&fPaths[flatPath->index() - 1]);
+ }
+ }
+
+ const SkTDArray<SkPicture* >& pictures = record.getPictureRefs();
+ fPictureCount = pictures.count();
+ if (fPictureCount > 0) {
+ fPictureRefs = SkNEW_ARRAY(SkPicture*, fPictureCount);
+ for (int i = 0; i < fPictureCount; i++) {
+ fPictureRefs[i] = pictures[i];
+ fPictureRefs[i]->ref();
+ }
+ }
+
+ 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);
+ paints = fPlayback->paints(&paintBytes);
+ paths = fPlayback->paths(&pathBytes);
+ pictures = fPlayback->pictures(&pictureBytes);
+ regions = fPlayback->regions(&regionBytes);
+ SkDebugf("playback size %zd (objects:%d) ", overallBytes, overall);
+ if (bitmaps != 0)
+ SkDebugf("bitmaps size %zd (bitmaps:%d) ", bitmapBytes, bitmaps);
+ if (paints != 0)
+ SkDebugf("paints size %zd (paints:%d) ", paintBytes, paints);
+ if (paths != 0)
+ SkDebugf("paths size %zd (paths:%d) ", pathBytes, paths);
+ if (pictures != 0)
+ SkDebugf("pictures size %zd (pictures:%d) ", pictureBytes, pictures);
+ if (regions != 0)
+ SkDebugf("regions size %zd (regions:%d) ", regionBytes, regions);
+ SkDebugf("\n");
+#endif
+}
+
+SkPicturePlayback::SkPicturePlayback(const SkPicturePlayback& src) {
+ this->init();
+
+ // copy the data from fReader
+ {
+ size_t size = src.fReader.size();
+ void* buffer = sk_malloc_throw(size);
+ memcpy(buffer, src.fReader.base(), size);
+ fReader.setMemory(buffer, size);
+ }
+
+ int i;
+
+ fBitmapCount = src.fBitmapCount;
+ fBitmaps = SkNEW_ARRAY(SkBitmap, fBitmapCount);
+ for (i = 0; i < fBitmapCount; i++) {
+ fBitmaps[i] = src.fBitmaps[i];
+ }
+
+ fMatrixCount = src.fMatrixCount;
+ fMatrices = SkNEW_ARRAY(SkMatrix, fMatrixCount);
+ memcpy(fMatrices, src.fMatrices, fMatrixCount * sizeof(SkMatrix));
+
+ fPaintCount = src.fPaintCount;
+ fPaints = SkNEW_ARRAY(SkPaint, fPaintCount);
+ for (i = 0; i < fPaintCount; i++) {
+ fPaints[i] = src.fPaints[i];
+ }
+
+ fPathCount = src.fPathCount;
+ fPaths = SkNEW_ARRAY(SkPath, fPathCount);
+ for (i = 0; i < fPathCount; i++) {
+ fPaths[i] = src.fPaths[i];
+ }
+
+ fPictureCount = src.fPictureCount;
+ fPictureRefs = SkNEW_ARRAY(SkPicture*, fPictureCount);
+ for (int i = 0; i < fPictureCount; i++) {
+ fPictureRefs[i] = src.fPictureRefs[i];
+ fPictureRefs[i]->ref();
+ }
+
+ fRegionCount = src.fRegionCount;
+ fRegions = SkNEW_ARRAY(SkRegion, fRegionCount);
+ for (i = 0; i < fRegionCount; i++) {
+ fRegions[i] = src.fRegions[i];
+ }
+}
+
+void SkPicturePlayback::init() {
+ fBitmaps = NULL;
+ fMatrices = NULL;
+ fPaints = NULL;
+ fPaths = NULL;
+ fPictureRefs = NULL;
+ fRegions = NULL;
+ fBitmapCount = fMatrixCount = fPaintCount = fPathCount = fPictureCount =
+ fRegionCount = 0;
+
+ fFactoryPlayback = NULL;
+}
+
+SkPicturePlayback::~SkPicturePlayback() {
+ sk_free((void*) fReader.base());
+
+ SkDELETE_ARRAY(fBitmaps);
+ SkDELETE_ARRAY(fMatrices);
+ SkDELETE_ARRAY(fPaints);
+ SkDELETE_ARRAY(fPaths);
+ SkDELETE_ARRAY(fRegions);
+
+ for (int i = 0; i < fPictureCount; i++) {
+ fPictureRefs[i]->unref();
+ }
+ SkDELETE_ARRAY(fPictureRefs);
+
+ SkDELETE(fFactoryPlayback);
+}
+
+void SkPicturePlayback::dumpSize() const {
+ SkDebugf("--- picture size: ops=%d bitmaps=%d [%d] matrices=%d [%d] paints=%d [%d] paths=%d regions=%d\n",
+ fReader.size(),
+ fBitmapCount, fBitmapCount * sizeof(SkBitmap),
+ fMatrixCount, fMatrixCount * sizeof(SkMatrix),
+ fPaintCount, fPaintCount * sizeof(SkPaint),
+ fPathCount,
+ fRegionCount);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+// The chunks are writte/read in this order...
+
+#define PICT_READER_TAG SkSetFourByteTag('r', 'e', 'a', 'd')
+#define PICT_FACTORY_TAG SkSetFourByteTag('f', 'a', 'c', 't')
+#define PICT_TYPEFACE_TAG SkSetFourByteTag('t', 'p', 'f', 'c')
+#define PICT_PICTURE_TAG SkSetFourByteTag('p', 'c', 't', 'r')
+#define PICT_ARRAYS_TAG SkSetFourByteTag('a', 'r', 'a', 'y')
+// these are all inside the ARRAYS tag
+#define PICT_BITMAP_TAG SkSetFourByteTag('b', 't', 'm', 'p')
+#define PICT_MATRIX_TAG SkSetFourByteTag('m', 't', 'r', 'x')
+#define PICT_PAINT_TAG SkSetFourByteTag('p', 'n', 't', ' ')
+#define PICT_PATH_TAG SkSetFourByteTag('p', 't', 'h', ' ')
+#define PICT_REGION_TAG SkSetFourByteTag('r', 'g', 'n', ' ')
+
+
+#include "SkStream.h"
+
+static void writeTagSize(SkFlattenableWriteBuffer& buffer, uint32_t tag,
+ uint32_t size) {
+ buffer.write32(tag);
+ buffer.write32(size);
+}
+
+static void writeTagSize(SkWStream* stream, uint32_t tag,
+ uint32_t size) {
+ stream->write32(tag);
+ stream->write32(size);
+}
+
+static void writeFactories(SkWStream* stream, const SkFactoryRecorder& rec) {
+ int count = rec.count();
+
+ writeTagSize(stream, PICT_FACTORY_TAG, count);
+
+ SkAutoSTMalloc<16, SkFlattenable::Factory> storage(count);
+ SkFlattenable::Factory* array = (SkFlattenable::Factory*)storage.get();
+ rec.get(array);
+
+ for (int i = 0; i < count; i++) {
+ const char* name = SkFlattenable::FactoryToName(array[i]);
+// SkDebugf("---- write factories [%d] %p <%s>\n", i, array[i], name);
+ if (NULL == name || 0 == *name) {
+ stream->writePackedUInt(0);
+ } else {
+ uint32_t len = strlen(name);
+ stream->writePackedUInt(len);
+ stream->write(name, len);
+ }
+ }
+}
+
+static void writeTypefaces(SkWStream* stream, const SkRefCntRecorder& rec) {
+ int count = rec.count();
+
+ writeTagSize(stream, PICT_TYPEFACE_TAG, count);
+
+ SkAutoSTMalloc<16, SkTypeface*> storage(count);
+ SkTypeface** array = (SkTypeface**)storage.get();
+ rec.get((SkRefCnt**)array);
+
+ for (int i = 0; i < count; i++) {
+ array[i]->serialize(stream);
+ }
+}
+
+void SkPicturePlayback::serialize(SkWStream* stream) const {
+ writeTagSize(stream, PICT_READER_TAG, fReader.size());
+ stream->write(fReader.base(), fReader.size());
+
+ SkRefCntRecorder typefaceRecorder;
+ SkFactoryRecorder factRecorder;
+
+ SkFlattenableWriteBuffer buffer(1024);
+
+ buffer.setFlags(SkFlattenableWriteBuffer::kCrossProcess_Flag);
+ buffer.setTypefaceRecorder(&typefaceRecorder);
+ buffer.setFactoryRecorder(&factRecorder);
+
+ int i;
+
+ writeTagSize(buffer, PICT_BITMAP_TAG, fBitmapCount);
+ for (i = 0; i < fBitmapCount; i++) {
+ fBitmaps[i].flatten(buffer);
+ }
+
+ writeTagSize(buffer, PICT_MATRIX_TAG, fMatrixCount);
+ buffer.writeMul4(fMatrices, fMatrixCount * sizeof(SkMatrix));
+
+ writeTagSize(buffer, PICT_PAINT_TAG, fPaintCount);
+ for (i = 0; i < fPaintCount; i++) {
+ fPaints[i].flatten(buffer);
+ }
+
+ writeTagSize(buffer, PICT_PATH_TAG, fPathCount);
+ for (i = 0; i < fPathCount; i++) {
+ fPaths[i].flatten(buffer);
+ }
+
+ 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);
+ }
+
+ // now we can write to the stream again
+
+ writeFactories(stream, factRecorder);
+ writeTypefaces(stream, typefaceRecorder);
+
+ writeTagSize(stream, PICT_PICTURE_TAG, fPictureCount);
+ for (i = 0; i < fPictureCount; i++) {
+ fPictureRefs[i]->serialize(stream);
+ }
+
+ writeTagSize(stream, PICT_ARRAYS_TAG, buffer.size());
+ buffer.writeToStream(stream);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static int readTagSize(SkFlattenableReadBuffer& buffer, uint32_t expectedTag) {
+ uint32_t tag = buffer.readU32();
+ if (tag != expectedTag) {
+ sk_throw();
+ }
+ return buffer.readU32();
+}
+
+static int readTagSize(SkStream* stream, uint32_t expectedTag) {
+ uint32_t tag = stream->readU32();
+ if (tag != expectedTag) {
+ sk_throw();
+ }
+ return stream->readU32();
+}
+
+SkPicturePlayback::SkPicturePlayback(SkStream* stream) {
+ this->init();
+
+ int i;
+
+ {
+ size_t size = readTagSize(stream, PICT_READER_TAG);
+ void* storage = sk_malloc_throw(size);
+ stream->read(storage, size);
+ fReader.setMemory(storage, size);
+ }
+
+ int factoryCount = readTagSize(stream, PICT_FACTORY_TAG);
+ fFactoryPlayback = SkNEW_ARGS(SkFactoryPlayback, (factoryCount));
+ for (i = 0; i < factoryCount; i++) {
+ SkString str;
+ int len = stream->readPackedUInt();
+ str.resize(len);
+ stream->read(str.writable_str(), len);
+// SkDebugf("--- factory playback [%d] <%s>\n", i, str.c_str());
+ fFactoryPlayback->base()[i] = SkFlattenable::NameToFactory(str.c_str());
+ }
+
+ int typefaceCount = readTagSize(stream, PICT_TYPEFACE_TAG);
+ fTFPlayback.setCount(typefaceCount);
+ for (i = 0; i < typefaceCount; i++) {
+ fTFPlayback.set(i, SkTypeface::Deserialize(stream))->unref();
+ }
+
+ fPictureCount = readTagSize(stream, PICT_PICTURE_TAG);
+ fPictureRefs = SkNEW_ARRAY(SkPicture*, fPictureCount);
+ for (i = 0; i < fPictureCount; i++) {
+ fPictureRefs[i] = SkNEW_ARGS(SkPicture, (stream));
+ }
+
+ /*
+ Now read the arrays chunk, and parse using a read buffer
+ */
+ uint32_t size = readTagSize(stream, PICT_ARRAYS_TAG);
+ SkAutoMalloc storage(size);
+ stream->read(storage.get(), size);
+
+ SkFlattenableReadBuffer buffer(storage.get(), size);
+ fFactoryPlayback->setupBuffer(buffer);
+ fTFPlayback.setupBuffer(buffer);
+
+ fBitmapCount = readTagSize(buffer, PICT_BITMAP_TAG);
+ fBitmaps = SkNEW_ARRAY(SkBitmap, fBitmapCount);
+ for (i = 0; i < fBitmapCount; i++) {
+ fBitmaps[i].unflatten(buffer);
+ }
+
+ fMatrixCount = readTagSize(buffer, PICT_MATRIX_TAG);
+ fMatrices = SkNEW_ARRAY(SkMatrix, fMatrixCount);
+ buffer.read(fMatrices, fMatrixCount * sizeof(SkMatrix));
+
+ fPaintCount = readTagSize(buffer, PICT_PAINT_TAG);
+ fPaints = SkNEW_ARRAY(SkPaint, fPaintCount);
+ for (i = 0; i < fPaintCount; i++) {
+ fPaints[i].unflatten(buffer);
+ }
+
+ fPathCount = readTagSize(buffer, PICT_PATH_TAG);
+ fPaths = SkNEW_ARRAY(SkPath, fPathCount);
+ for (i = 0; i < fPathCount; i++) {
+ fPaths[i].unflatten(buffer);
+ }
+
+ fRegionCount = readTagSize(buffer, PICT_REGION_TAG);
+ fRegions = SkNEW_ARRAY(SkRegion, fRegionCount);
+ for (i = 0; i < fRegionCount; i++) {
+ uint32_t size = buffer.readU32();
+ uint32_t bytes = fRegions[i].unflatten(buffer.skip(size));
+ SkASSERT(size == bytes);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+void SkPicturePlayback::draw(SkCanvas& canvas) {
+#ifdef ENABLE_TIME_DRAW
+ SkAutoTime at("SkPicture::draw", 50);
+#endif
+
+ TextContainer text;
+ fReader.rewind();
+ bool clipBoundsDirty = true;
+ SkRect clipBounds;
+
+ while (!fReader.eof()) {
+ switch (fReader.readInt()) {
+ case CLIP_PATH: {
+ const SkPath& path = getPath();
+ SkRegion::Op op = (SkRegion::Op) getInt();
+ size_t offsetToRestore = getInt();
+ // HACK (false) until I can handle op==kReplace <reed>
+ if (!canvas.clipPath(path, op) && false) {
+ //SkDebugf("---- skip clipPath for %d bytes\n", offsetToRestore - fReader.offset());
+ fReader.setOffset(offsetToRestore);
+ }
+ clipBoundsDirty = true;
+ } break;
+ case CLIP_REGION: {
+ const SkRegion& region = getRegion();
+ SkRegion::Op op = (SkRegion::Op) getInt();
+ size_t offsetToRestore = getInt();
+ if (!canvas.clipRegion(region, op)) {
+ //SkDebugf("---- skip clipDeviceRgn for %d bytes\n", offsetToRestore - fReader.offset());
+ fReader.setOffset(offsetToRestore);
+ }
+ clipBoundsDirty = true;
+ } break;
+ case CLIP_RECT: {
+ const SkRect* rect = fReader.skipRect();
+ SkRegion::Op op = (SkRegion::Op) getInt();
+ size_t offsetToRestore = getInt();
+ if (!canvas.clipRect(*rect, op)) {
+ //SkDebugf("---- skip clipRect for %d bytes\n", offsetToRestore - fReader.offset());
+ fReader.setOffset(offsetToRestore);
+ }
+ clipBoundsDirty = true;
+ } break;
+ case CONCAT:
+ canvas.concat(*getMatrix());
+ clipBoundsDirty = true;
+ break;
+ case DRAW_BITMAP: {
+ const SkPaint* paint = getPaint();
+ const SkBitmap& bitmap = getBitmap();
+ const SkPoint* loc = fReader.skipPoint();
+ canvas.drawBitmap(bitmap, loc->fX, loc->fY, paint);
+ } break;
+ case DRAW_BITMAP_RECT: {
+ const SkPaint* paint = getPaint();
+ const SkBitmap& bitmap = getBitmap();
+ const SkIRect* src = this->getIRectPtr(); // may be null
+ const SkRect* dst = fReader.skipRect(); // required
+ canvas.drawBitmapRect(bitmap, src, *dst, paint);
+ } break;
+ case DRAW_BITMAP_MATRIX: {
+ const SkPaint* paint = getPaint();
+ const SkBitmap& bitmap = getBitmap();
+ const SkMatrix* matrix = getMatrix();
+ canvas.drawBitmapMatrix(bitmap, *matrix, paint);
+ } break;
+ case DRAW_PAINT:
+ canvas.drawPaint(*getPaint());
+ break;
+ case DRAW_PATH: {
+ const SkPaint& paint = *getPaint();
+ const SkPath& path = getPath();
+ canvas.drawPath(path, paint);
+ } break;
+ case DRAW_PICTURE:
+ canvas.drawPicture(getPicture());
+ break;
+ case DRAW_POINTS: {
+ const SkPaint& paint = *getPaint();
+ SkCanvas::PointMode mode = (SkCanvas::PointMode)getInt();
+ size_t count = getInt();
+ const SkPoint* pts = (const SkPoint*)fReader.skip(sizeof(SkPoint) * count);
+ canvas.drawPoints(mode, count, pts, paint);
+ } break;
+ case DRAW_POS_TEXT: {
+ const SkPaint& paint = *getPaint();
+ getText(&text);
+ size_t points = getInt();
+ const SkPoint* pos = (const SkPoint*)fReader.skip(points * sizeof(SkPoint));
+ canvas.drawPosText(text.text(), text.length(), pos, paint);
+ } break;
+ case DRAW_POS_TEXT_H: {
+ const SkPaint& paint = *getPaint();
+ getText(&text);
+ size_t points = getInt();
+ size_t byteLength = text.length();
+ const SkScalar* xpos = (const SkScalar*)fReader.skip((3 + points) * sizeof(SkScalar));
+ const SkScalar top = *xpos++;
+ const SkScalar bottom = *xpos++;
+ const SkScalar constY = *xpos++;
+ // would be nice to do this before we load the other fields
+ // (especially the text block). To do that we'd need to record
+ // the number of bytes to skip...
+ if (clipBoundsDirty) {
+ if (!canvas.getClipBounds(&clipBounds)) {
+ clipBounds.setEmpty();
+ }
+ clipBoundsDirty = false;
+ }
+ if (top < clipBounds.fBottom && bottom > clipBounds.fTop) {
+ canvas.drawPosTextH(text.text(), byteLength, xpos, constY,
+ paint);
+ }
+ } break;
+ case DRAW_RECT_GENERAL: {
+ const SkPaint& paint = *getPaint();
+ canvas.drawRect(*fReader.skipRect(), paint);
+ } break;
+ case DRAW_RECT_SIMPLE: {
+ const SkPaint& paint = *getPaint();
+ const SkRect* rect = fReader.skipRect();
+ if (clipBoundsDirty) {
+ if (!canvas.getClipBounds(&clipBounds)) {
+ clipBounds.setEmpty();
+ }
+ clipBoundsDirty = false;
+ }
+ if (SkRect::Intersects(clipBounds, *rect)) {
+ canvas.drawRect(*rect, paint);
+ }
+ } break;
+ case DRAW_SPRITE: {
+ const SkPaint* paint = getPaint();
+ const SkBitmap& bitmap = getBitmap();
+ int left = getInt();
+ int top = getInt();
+ canvas.drawSprite(bitmap, left, top, paint);
+ } break;
+ case DRAW_TEXT: {
+ const SkPaint& paint = *getPaint();
+ getText(&text);
+ const SkScalar* ptr = (const SkScalar*)fReader.skip(4 * sizeof(SkScalar));
+ // ptr[0] == x
+ // ptr[1] == y
+ // ptr[2] == top
+ // ptr[3] == bottom
+ if (clipBoundsDirty) {
+ if (!canvas.getClipBounds(&clipBounds)) {
+ clipBounds.setEmpty();
+ }
+ clipBoundsDirty = false;
+ }
+ if (ptr[2] < clipBounds.fBottom && ptr[3] > clipBounds.fTop) {
+ canvas.drawText(text.text(), text.length(), ptr[0], ptr[1],
+ paint);
+ }
+ } break;
+ case DRAW_TEXT_ON_PATH: {
+ const SkPaint& paint = *getPaint();
+ getText(&text);
+ const SkPath& path = getPath();
+ const SkMatrix* matrix = getMatrix();
+ canvas.drawTextOnPath(text.text(), text.length(), path,
+ matrix, paint);
+ } break;
+ case DRAW_VERTICES: {
+ const SkPaint& paint = *getPaint();
+ DrawVertexFlags flags = (DrawVertexFlags)getInt();
+ SkCanvas::VertexMode vmode = (SkCanvas::VertexMode)getInt();
+ int vCount = getInt();
+ const SkPoint* verts = (const SkPoint*)fReader.skip(
+ vCount * sizeof(SkPoint));
+ const SkPoint* texs = NULL;
+ const SkColor* colors = NULL;
+ const uint16_t* indices = NULL;
+ int iCount = 0;
+ if (flags & DRAW_VERTICES_HAS_TEXS) {
+ texs = (const SkPoint*)fReader.skip(
+ vCount * sizeof(SkPoint));
+ }
+ if (flags & DRAW_VERTICES_HAS_COLORS) {
+ colors = (const SkColor*)fReader.skip(
+ vCount * sizeof(SkColor));
+ }
+ if (flags & DRAW_VERTICES_HAS_INDICES) {
+ iCount = getInt();
+ indices = (const uint16_t*)fReader.skip(
+ iCount * sizeof(uint16_t));
+ }
+ canvas.drawVertices(vmode, vCount, verts, texs, colors, NULL,
+ indices, iCount, paint);
+ } break;
+ case RESTORE:
+ canvas.restore();
+ clipBoundsDirty = true;
+ break;
+ case ROTATE:
+ canvas.rotate(getScalar());
+ clipBoundsDirty = true;
+ break;
+ case SAVE:
+ canvas.save((SkCanvas::SaveFlags) getInt());
+ break;
+ case SAVE_LAYER: {
+ const SkRect* boundsPtr = getRectPtr();
+ const SkPaint* paint = getPaint();
+ canvas.saveLayer(boundsPtr, paint, (SkCanvas::SaveFlags) getInt());
+ } break;
+ case SCALE: {
+ SkScalar sx = getScalar();
+ SkScalar sy = getScalar();
+ canvas.scale(sx, sy);
+ clipBoundsDirty = true;
+ } break;
+ case SKEW: {
+ SkScalar sx = getScalar();
+ SkScalar sy = getScalar();
+ canvas.skew(sx, sy);
+ clipBoundsDirty = true;
+ } break;
+ case TRANSLATE: {
+ SkScalar dx = getScalar();
+ SkScalar dy = getScalar();
+ canvas.translate(dx, dy);
+ clipBoundsDirty = true;
+ } break;
+ default:
+ SkASSERT(0);
+ }
+ }
+
+// this->dumpSize();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#if 0
+uint32_t SkPicturePlayback::flatten(void* storage) const {
+ SkWBuffer buffer(storage);
+ buffer.write32(fBitmapCount);
+ int index;
+ for (index = 0; index < fBitmapCount; index++) {
+ const SkBitmap& bitmap = fBitmaps[index];
+ uint32_t size = bitmap.flatten(NULL, true);
+ buffer.write32(size);
+ void* local = buffer.skip(size);
+ bitmap.flatten(local, true);
+ }
+ buffer.write32(fPaintCount);
+ for (index = 0; index < fPaintCount; index++) {
+ SkFlattenableWriteBuffer flatWrite;
+ const SkPaint& paint = fPaints[index];
+ SkFlatPaint::Write(&flatWrite, paint);
+ uint32_t size = flatWrite.pos();
+ buffer.write32(size);
+ void* local = buffer.skip(size);
+ flatWrite.reset(local);
+ SkFlatPaint::Write(&flatWrite, paint);
+ }
+ buffer.write32(fPathCount);
+ for (index = 0; index < fPathCount; index++) {
+ const SkPath& path = fPaths[index];
+ uint32_t size = path.flatten(NULL);
+ buffer.write32(size);
+ void* local = buffer.skip(size);
+ path.flatten(local);
+ }
+
+#if 0
+ buffer.write32(fPictureCount);
+ for (index = 0; index < fPictureCount; index++) {
+ const SkPicture& picture = fPictures[index];
+ uint32_t size = picture.flatten(NULL);
+ buffer.write32(size);
+ void* local = buffer.skip(size);
+ picture.flatten(local);
+ }
+#endif
+
+ buffer.write32(fRegionCount);
+ for (index = 0; index < fRegionCount; index++) {
+ const SkRegion& region = fRegions[index];
+ size_t size = region.computeBufferSize();
+ buffer.write32(size);
+ void* local = buffer.skip(size);
+ region.writeToBuffer(local);
+ }
+ fReader.rewind();
+ size_t length = fReader.size();
+ buffer.write32(length);
+ memcpy(buffer.skip(length), fReader.base(), length);
+ return (uint32_t) buffer.pos();
+}
+
+void SkPicturePlayback::unflatten(const void* storage) {
+ SkRBuffer buffer(storage);
+ int index;
+ fBitmapCount = buffer.readU32();
+ fBitmaps = new SkBitmap[fBitmapCount];
+ for (index = 0; index < fBitmapCount; index++) {
+ uint32_t size = buffer.readU32();
+ const void* local = buffer.skip(size);
+ fBitmaps[index].unflatten(local);
+ }
+ fPaintCount = buffer.readU32();
+ fPaints = new SkPaint[fPaintCount];
+ for (index = 0; index < fPaintCount; index++) {
+ uint32_t size = buffer.readU32();
+ const void* local = buffer.skip(size);
+ SkFlatPaint::Read(local, &fPaints[index]);
+ }
+ fPathCount = buffer.readU32();
+ fPaths = new SkPath[fPathCount];
+ for (index = 0; index < fPathCount; index++) {
+ uint32_t size = buffer.readU32();
+ const void* local = buffer.skip(size);
+ fPaths[index].unflatten(local);
+ }
+
+#if 0
+ fPictureCount = buffer.readU32();
+ fPictures = new SkPicture[fPictureCount];
+ for (index = 0; index < fPictureCount; index++) {
+ uint32_t size = buffer.readU32();
+ const void* local = buffer.skip(size);
+ fPictures[index].unflatten(local);
+ }
+#endif
+
+ fRegionCount = buffer.readU32();
+ fRegions = new SkRegion[fRegionCount];
+ for (index = 0; index < fRegionCount; index++) {
+ uint32_t size = buffer.readU32();
+ const void* local = buffer.skip(size);
+ fRegions[index].readFromBuffer(local);
+ }
+ int32_t length = buffer.readS32();
+ const void* stream = buffer.skip(length);
+ fReader.setMemory(stream, length);
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef SK_DEBUG_SIZE
+int SkPicturePlayback::size(size_t* sizePtr) {
+ int objects = bitmaps(sizePtr);
+ objects += paints(sizePtr);
+ objects += paths(sizePtr);
+ objects += pictures(sizePtr);
+ objects += regions(sizePtr);
+ *sizePtr = fReader.size();
+ return objects;
+}
+
+int SkPicturePlayback::bitmaps(size_t* size) {
+ size_t result = 0;
+ for (int index = 0; index < fBitmapCount; index++) {
+ // const SkBitmap& bitmap = fBitmaps[index];
+ result += sizeof(SkBitmap); // bitmap->size();
+ }
+ *size = result;
+ return fBitmapCount;
+}
+
+int SkPicturePlayback::paints(size_t* size) {
+ size_t result = 0;
+ for (int index = 0; index < fPaintCount; index++) {
+ // const SkPaint& paint = fPaints[index];
+ result += sizeof(SkPaint); // paint->size();
+ }
+ *size = result;
+ return fPaintCount;
+}
+
+int SkPicturePlayback::paths(size_t* size) {
+ size_t result = 0;
+ for (int index = 0; index < fPathCount; index++) {
+ const SkPath& path = fPaths[index];
+ result += path.flatten(NULL);
+ }
+ *size = result;
+ return fPathCount;
+}
+
+int SkPicturePlayback::regions(size_t* size) {
+ size_t result = 0;
+ for (int index = 0; index < fRegionCount; index++) {
+ // const SkRegion& region = fRegions[index];
+ result += sizeof(SkRegion); // region->size();
+ }
+ *size = result;
+ return fRegionCount;
+}
+#endif
+
+#ifdef SK_DEBUG_DUMP
+void SkPicturePlayback::dumpBitmap(const SkBitmap& bitmap) const {
+ char pBuffer[DUMP_BUFFER_SIZE];
+ char* bufferPtr = pBuffer;
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "BitmapData bitmap%p = {", &bitmap);
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kWidth, %d}, ", bitmap.width());
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kHeight, %d}, ", bitmap.height());
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kRowBytes, %d}, ", bitmap.rowBytes());
+// start here;
+ SkDebugf("%s{0}};\n", pBuffer);
+}
+
+void dumpMatrix(const SkMatrix& matrix) const {
+ SkMatrix defaultMatrix;
+ defaultMatrix.reset();
+ char pBuffer[DUMP_BUFFER_SIZE];
+ char* bufferPtr = pBuffer;
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "MatrixData matrix%p = {", &matrix);
+ SkScalar scaleX = matrix.getScaleX();
+ if (scaleX != defaultMatrix.getScaleX())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kScaleX, %g}, ", SkScalarToFloat(scaleX));
+ SkScalar scaleY = matrix.getScaleY();
+ if (scaleY != defaultMatrix.getScaleY())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kScaleY, %g}, ", SkScalarToFloat(scaleY));
+ SkScalar skewX = matrix.getSkewX();
+ if (skewX != defaultMatrix.getSkewX())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kSkewX, %g}, ", SkScalarToFloat(skewX));
+ SkScalar skewY = matrix.getSkewY();
+ if (skewY != defaultMatrix.getSkewY())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kSkewY, %g}, ", SkScalarToFloat(skewY));
+ SkScalar translateX = matrix.getTranslateX();
+ if (translateX != defaultMatrix.getTranslateX())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kTranslateX, %g}, ", SkScalarToFloat(translateX));
+ SkScalar translateY = matrix.getTranslateY();
+ if (translateY != defaultMatrix.getTranslateY())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kTranslateY, %g}, ", SkScalarToFloat(translateY));
+ SkScalar perspX = matrix.getPerspX();
+ if (perspX != defaultMatrix.getPerspX())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kPerspX, %g}, ", SkFractToFloat(perspX));
+ SkScalar perspY = matrix.getPerspY();
+ if (perspY != defaultMatrix.getPerspY())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kPerspY, %g}, ", SkFractToFloat(perspY));
+ SkDebugf("%s{0}};\n", pBuffer);
+}
+
+void dumpPaint(const SkPaint& paint) const {
+ SkPaint defaultPaint;
+ char pBuffer[DUMP_BUFFER_SIZE];
+ char* bufferPtr = pBuffer;
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "PaintPointers paintPtrs%p = {", &paint);
+ const SkTypeface* typeface = paint.getTypeface();
+ if (typeface != defaultPaint.getTypeface())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kTypeface, %p}, ", typeface);
+ const SkPathEffect* pathEffect = paint.getPathEffect();
+ if (pathEffect != defaultPaint.getPathEffect())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kPathEffect, %p}, ", pathEffect);
+ const SkShader* shader = paint.getShader();
+ if (shader != defaultPaint.getShader())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kShader, %p}, ", shader);
+ const SkXfermode* xfermode = paint.getXfermode();
+ if (xfermode != defaultPaint.getXfermode())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kXfermode, %p}, ", xfermode);
+ const SkMaskFilter* maskFilter = paint.getMaskFilter();
+ if (maskFilter != defaultPaint.getMaskFilter())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kMaskFilter, %p}, ", maskFilter);
+ const SkColorFilter* colorFilter = paint.getColorFilter();
+ if (colorFilter != defaultPaint.getColorFilter())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kColorFilter, %p}, ", colorFilter);
+ const SkRasterizer* rasterizer = paint.getRasterizer();
+ if (rasterizer != defaultPaint.getRasterizer())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kRasterizer, %p}, ", rasterizer);
+ const SkDrawLooper* drawLooper = paint.getLooper();
+ if (drawLooper != defaultPaint.getLooper())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kDrawLooper, %p}, ", drawLooper);
+ SkDebugf("%s{0}};\n", pBuffer);
+ bufferPtr = pBuffer;
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "PaintScalars paintScalars%p = {", &paint);
+ SkScalar textSize = paint.getTextSize();
+ if (textSize != defaultPaint.getTextSize())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kTextSize, %g}, ", SkScalarToFloat(textSize));
+ SkScalar textScaleX = paint.getTextScaleX();
+ if (textScaleX != defaultPaint.getTextScaleX())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kTextScaleX, %g}, ", SkScalarToFloat(textScaleX));
+ SkScalar textSkewX = paint.getTextSkewX();
+ if (textSkewX != defaultPaint.getTextSkewX())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kTextSkewX, %g}, ", SkScalarToFloat(textSkewX));
+ SkScalar strokeWidth = paint.getStrokeWidth();
+ if (strokeWidth != defaultPaint.getStrokeWidth())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kStrokeWidth, %g}, ", SkScalarToFloat(strokeWidth));
+ SkScalar strokeMiter = paint.getStrokeMiter();
+ if (strokeMiter != defaultPaint.getStrokeMiter())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kStrokeMiter, %g}, ", SkScalarToFloat(strokeMiter));
+ SkDebugf("%s{0}};\n", pBuffer);
+ bufferPtr = pBuffer;
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "PaintInts = paintInts%p = {", &paint);
+ unsigned color = paint.getColor();
+ if (color != defaultPaint.getColor())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kColor, 0x%x}, ", color);
+ unsigned flags = paint.getFlags();
+ if (flags != defaultPaint.getFlags())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kFlags, 0x%x}, ", flags);
+ int align = paint.getTextAlign();
+ if (align != defaultPaint.getTextAlign())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kAlign, 0x%x}, ", align);
+ int strokeCap = paint.getStrokeCap();
+ if (strokeCap != defaultPaint.getStrokeCap())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kStrokeCap, 0x%x}, ", strokeCap);
+ int strokeJoin = paint.getStrokeJoin();
+ if (strokeJoin != defaultPaint.getStrokeJoin())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kAlign, 0x%x}, ", strokeJoin);
+ int style = paint.getStyle();
+ if (style != defaultPaint.getStyle())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kStyle, 0x%x}, ", style);
+ int textEncoding = paint.getTextEncoding();
+ if (textEncoding != defaultPaint.getTextEncoding())
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "{kTextEncoding, 0x%x}, ", textEncoding);
+ SkDebugf("%s{0}};\n", pBuffer);
+
+ SkDebugf("PaintData paint%p = {paintPtrs%p, paintScalars%p, paintInts%p};\n",
+ &paint, &paint, &paint, &paint);
+}
+
+void SkPicturePlayback::dumpPath(const SkPath& path) const {
+ SkDebugf("path dump unimplemented\n");
+}
+
+void SkPicturePlayback::dumpPicture(const SkPicture& picture) const {
+ SkDebugf("picture dump unimplemented\n");
+}
+
+void SkPicturePlayback::dumpRegion(const SkRegion& region) const {
+ SkDebugf("region dump unimplemented\n");
+}
+
+int SkPicturePlayback::dumpDrawType(char* bufferPtr, char* buffer, DrawType drawType) {
+ return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
+ "k%s, ", DrawTypeToString(drawType));
+}
+
+int SkPicturePlayback::dumpInt(char* bufferPtr, char* buffer, char* name) {
+ return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
+ "%s:%d, ", name, getInt());
+}
+
+int SkPicturePlayback::dumpRect(char* bufferPtr, char* buffer, char* name) {
+ const SkRect* rect = fReader.skipRect();
+ return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
+ "%s:{l:%g t:%g r:%g b:%g}, ", name, SkScalarToFloat(rect.fLeft),
+ SkScalarToFloat(rect.fTop),
+ SkScalarToFloat(rect.fRight), SkScalarToFloat(rect.fBottom));
+}
+
+int SkPicturePlayback::dumpPoint(char* bufferPtr, char* buffer, char* name) {
+ SkPoint pt;
+ getPoint(&pt);
+ return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
+ "%s:{x:%g y:%g}, ", name, SkScalarToFloat(pt.fX),
+ SkScalarToFloat(pt.fY));
+}
+
+void SkPicturePlayback::dumpPointArray(char** bufferPtrPtr, char* buffer, int count) {
+ char* bufferPtr = *bufferPtrPtr;
+ const SkPoint* pts = (const SkPoint*)fReadStream.getAtPos();
+ fReadStream.skip(sizeof(SkPoint) * count);
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
+ "count:%d {", count);
+ for (int index = 0; index < count; index++)
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
+ "{x:%g y:%g}, ", SkScalarToFloat(pts[index].fX),
+ SkScalarToFloat(pts[index].fY));
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
+ "} ");
+ *bufferPtrPtr = bufferPtr;
+}
+
+int SkPicturePlayback::dumpPtr(char* bufferPtr, char* buffer, char* name, void* ptr) {
+ return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
+ "%s:%p, ", name, ptr);
+}
+
+int SkPicturePlayback::dumpRectPtr(char* bufferPtr, char* buffer, char* name) {
+ char result;
+ fReadStream.read(&result, sizeof(result));
+ if (result)
+ return dumpRect(bufferPtr, buffer, name);
+ else
+ return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
+ "%s:NULL, ", name);
+}
+
+int SkPicturePlayback::dumpScalar(char* bufferPtr, char* buffer, char* name) {
+ return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
+ "%s:%d, ", name, getScalar());
+}
+
+void SkPicturePlayback::dumpText(char** bufferPtrPtr, char* buffer) {
+ char* bufferPtr = *bufferPtrPtr;
+ int length = getInt();
+ bufferPtr += dumpDrawType(bufferPtr, buffer);
+ fReadStream.skipToAlign4();
+ char* text = (char*) fReadStream.getAtPos();
+ fReadStream.skip(length);
+ bufferPtr += dumpInt(bufferPtr, buffer, "length");
+ int limit = DUMP_BUFFER_SIZE - (bufferPtr - buffer) - 2;
+ length >>= 1;
+ if (limit > length)
+ limit = length;
+ if (limit > 0) {
+ *bufferPtr++ = '"';
+ for (int index = 0; index < limit; index++) {
+ *bufferPtr++ = *(unsigned short*) text;
+ text += sizeof(unsigned short);
+ }
+ *bufferPtr++ = '"';
+ }
+ *bufferPtrPtr = bufferPtr;
+}
+
+#define DUMP_DRAWTYPE(drawType) \
+ bufferPtr += dumpDrawType(bufferPtr, buffer, drawType)
+
+#define DUMP_INT(name) \
+ bufferPtr += dumpInt(bufferPtr, buffer, #name)
+
+#define DUMP_RECT_PTR(name) \
+ bufferPtr += dumpRectPtr(bufferPtr, buffer, #name)
+
+#define DUMP_POINT(name) \
+ bufferPtr += dumpRect(bufferPtr, buffer, #name)
+
+#define DUMP_RECT(name) \
+ bufferPtr += dumpRect(bufferPtr, buffer, #name)
+
+#define DUMP_POINT_ARRAY(count) \
+ dumpPointArray(&bufferPtr, buffer, count)
+
+#define DUMP_PTR(name, ptr) \
+ bufferPtr += dumpPtr(bufferPtr, buffer, #name, (void*) ptr)
+
+#define DUMP_SCALAR(name) \
+ bufferPtr += dumpScalar(bufferPtr, buffer, #name)
+
+#define DUMP_TEXT() \
+ dumpText(&bufferPtr, buffer)
+
+void SkPicturePlayback::dumpStream() {
+ SkDebugf("RecordStream stream = {\n");
+ DrawType drawType;
+ TextContainer text;
+ fReadStream.rewind();
+ char buffer[DUMP_BUFFER_SIZE], * bufferPtr;
+ while (fReadStream.read(&drawType, sizeof(drawType))) {
+ bufferPtr = buffer;
+ DUMP_DRAWTYPE(drawType);
+ switch (drawType) {
+ case CLIP_PATH: {
+ DUMP_PTR(SkPath, &getPath());
+ DUMP_INT(SkRegion::Op);
+ DUMP_INT(offsetToRestore);
+ } break;
+ case CLIP_REGION: {
+ DUMP_PTR(SkRegion, &getRegion());
+ DUMP_INT(SkRegion::Op);
+ DUMP_INT(offsetToRestore);
+ } break;
+ case CLIP_RECT: {
+ DUMP_RECT(rect);
+ DUMP_INT(SkRegion::Op);
+ DUMP_INT(offsetToRestore);
+ } break;
+ case CONCAT:
+ DUMP_PTR(SkMatrix, getMatrix());
+ break;
+ case DRAW_BITMAP: {
+ DUMP_PTR(SkPaint, getPaint());
+ DUMP_PTR(SkBitmap, &getBitmap());
+ DUMP_SCALAR(left);
+ DUMP_SCALAR(top);
+ } break;
+ case DRAW_PAINT:
+ DUMP_PTR(SkPaint, getPaint());
+ break;
+ case DRAW_PATH: {
+ DUMP_PTR(SkPaint, getPaint());
+ DUMP_PTR(SkPath, &getPath());
+ } break;
+ case DRAW_PICTURE: {
+ DUMP_PTR(SkPicture, &getPicture());
+ } break;
+ case DRAW_POINTS: {
+ DUMP_PTR(SkPaint, getPaint());
+ (void)getInt(); // PointMode
+ size_t count = getInt();
+ fReadStream.skipToAlign4();
+ DUMP_POINT_ARRAY(count);
+ } break;
+ case DRAW_POS_TEXT: {
+ DUMP_PTR(SkPaint, getPaint());
+ DUMP_TEXT();
+ size_t points = getInt();
+ fReadStream.skipToAlign4();
+ DUMP_POINT_ARRAY(points);
+ } break;
+ case DRAW_POS_TEXT_H: {
+ DUMP_PTR(SkPaint, getPaint());
+ DUMP_TEXT();
+ size_t points = getInt();
+ fReadStream.skipToAlign4();
+ DUMP_SCALAR(top);
+ DUMP_SCALAR(bottom);
+ DUMP_SCALAR(constY);
+ DUMP_POINT_ARRAY(points);
+ } break;
+ case DRAW_RECT_GENERAL:
+ case DRAW_RECT_SIMPLE: {
+ DUMP_PTR(SkPaint, getPaint());
+ DUMP_RECT(rect);
+ } break;
+ case DRAW_SPRITE: {
+ DUMP_PTR(SkPaint, getPaint());
+ DUMP_PTR(SkBitmap, &getBitmap());
+ DUMP_SCALAR(left);
+ DUMP_SCALAR(top);
+ } break;
+ case DRAW_TEXT: {
+ DUMP_PTR(SkPaint, getPaint());
+ DUMP_TEXT();
+ DUMP_SCALAR(x);
+ DUMP_SCALAR(y);
+ } break;
+ case DRAW_TEXT_ON_PATH: {
+ DUMP_PTR(SkPaint, getPaint());
+ DUMP_TEXT();
+ DUMP_PTR(SkPath, &getPath());
+ DUMP_PTR(SkMatrix, getMatrix());
+ } break;
+ case RESTORE:
+ break;
+ case ROTATE:
+ DUMP_SCALAR(rotate);
+ break;
+ case SAVE:
+ DUMP_INT(SkCanvas::SaveFlags);
+ break;
+ case SAVE_LAYER: {
+ DUMP_RECT_PTR(layer);
+ DUMP_PTR(SkPaint, getPaint());
+ DUMP_INT(SkCanvas::SaveFlags);
+ } break;
+ case SCALE: {
+ DUMP_SCALAR(sx);
+ DUMP_SCALAR(sy);
+ } break;
+ case SKEW: {
+ DUMP_SCALAR(sx);
+ DUMP_SCALAR(sy);
+ } break;
+ case TRANSLATE: {
+ DUMP_SCALAR(dx);
+ DUMP_SCALAR(dy);
+ } break;
+ default:
+ SkASSERT(0);
+ }
+ SkDebugf("%s\n", buffer);
+ }
+}
+
+void SkPicturePlayback::dump() const {
+ char pBuffer[DUMP_BUFFER_SIZE];
+ char* bufferPtr = pBuffer;
+ int index;
+ if (fBitmapCount > 0)
+ SkDebugf("// bitmaps (%d)\n", fBitmapCount);
+ for (index = 0; index < fBitmapCount; index++) {
+ const SkBitmap& bitmap = fBitmaps[index];
+ dumpBitmap(bitmap);
+ }
+ if (fBitmapCount > 0)
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "Bitmaps bitmaps = {");
+ for (index = 0; index < fBitmapCount; index++)
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "bitmap%p, ", &fBitmaps[index]);
+ if (fBitmapCount > 0)
+ SkDebugf("%s0};\n", pBuffer);
+
+ if (fMatrixCount > 0)
+ SkDebugf("// matrices (%d)\n", fMatrixCount);
+ for (index = 0; index < fMatrixCount; index++) {
+ const SkMatrix& matrix = fMatrices[index];
+ dumpMatrix(matrix);
+ }
+ bufferPtr = pBuffer;
+ if (fMatrixCount > 0)
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "Matrices matrices = {");
+ for (index = 0; index < fMatrixCount; index++)
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "matrix%p, ", &fMatrices[index]);
+ if (fMatrixCount > 0)
+ SkDebugf("%s0};\n", pBuffer);
+
+ if (fPaintCount > 0)
+ SkDebugf("// paints (%d)\n", fPaintCount);
+ for (index = 0; index < fPaintCount; index++) {
+ const SkPaint& paint = fPaints[index];
+ dumpPaint(paint);
+ }
+ bufferPtr = pBuffer;
+ if (fPaintCount > 0)
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "Paints paints = {");
+ for (index = 0; index < fPaintCount; index++)
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "paint%p, ", &fPaints[index]);
+ if (fPaintCount > 0)
+ SkDebugf("%s0};\n", pBuffer);
+
+ for (index = 0; index < fPathCount; index++) {
+ const SkPath& path = fPaths[index];
+ dumpPath(path);
+ }
+ bufferPtr = pBuffer;
+ if (fPathCount > 0)
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "Paths paths = {");
+ for (index = 0; index < fPathCount; index++)
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "path%p, ", &fPaths[index]);
+ if (fPathCount > 0)
+ SkDebugf("%s0};\n", pBuffer);
+
+ for (index = 0; index < fPictureCount; index++) {
+ dumpPicture(*fPictureRefs[index]);
+ }
+ bufferPtr = pBuffer;
+ if (fPictureCount > 0)
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "Pictures pictures = {");
+ for (index = 0; index < fPictureCount; index++)
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "picture%p, ", fPictureRefs[index]);
+ if (fPictureCount > 0)
+ SkDebugf("%s0};\n", pBuffer);
+
+ for (index = 0; index < fRegionCount; index++) {
+ const SkRegion& region = fRegions[index];
+ dumpRegion(region);
+ }
+ bufferPtr = pBuffer;
+ if (fRegionCount > 0)
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "Regions regions = {");
+ for (index = 0; index < fRegionCount; index++)
+ bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
+ "region%p, ", &fRegions[index]);
+ if (fRegionCount > 0)
+ SkDebugf("%s0};\n", pBuffer);
+
+ const_cast<SkPicturePlayback*>(this)->dumpStream();
+}
+
+#endif
+
diff --git a/skia/picture/SkPicturePlayback.h b/skia/picture/SkPicturePlayback.h
new file mode 100644
index 0000000..7e99bd0
--- /dev/null
+++ b/skia/picture/SkPicturePlayback.h
@@ -0,0 +1,166 @@
+#ifndef SkPicturePlayback_DEFINED
+#define SkPicturePlayback_DEFINED
+
+#include "SkPicture.h"
+#include "SkReader32.h"
+
+#include "SkBitmap.h"
+#include "SkMatrix.h"
+#include "SkPaint.h"
+#include "SkPath.h"
+#include "SkRegion.h"
+#include "SkPictureFlat.h"
+
+class SkPictureRecord;
+class SkStream;
+class SkWStream;
+
+class SkPicturePlayback {
+public:
+ SkPicturePlayback();
+ SkPicturePlayback(const SkPicturePlayback& src);
+ explicit SkPicturePlayback(const SkPictureRecord& record);
+ explicit SkPicturePlayback(SkStream*);
+
+ virtual ~SkPicturePlayback();
+
+ void draw(SkCanvas& canvas);
+
+ void serialize(SkWStream*) const;
+
+ void dumpSize() const;
+
+private:
+
+ class TextContainer {
+ public:
+ size_t length() { return fByteLength; }
+ const void* text() { return (const void*) fText; }
+ size_t fByteLength;
+ const char* fText;
+ };
+
+ const SkBitmap& getBitmap() {
+ int index = getInt();
+ SkASSERT(index > 0);
+ return fBitmaps[index - 1];
+ }
+
+ int getIndex() { return fReader.readInt(); }
+ int getInt() { return fReader.readInt(); }
+
+ const SkMatrix* getMatrix() {
+ int index = getInt();
+ if (index == 0) {
+ return NULL;
+ }
+ SkASSERT(index > 0 && index <= fMatrixCount);
+ return &fMatrices[index - 1];
+ }
+
+ const SkPath& getPath() {
+ int index = getInt();
+ SkASSERT(index > 0 && index <= fPathCount);
+ return fPaths[index - 1];
+ }
+
+ SkPicture& getPicture() {
+ int index = getInt();
+ SkASSERT(index > 0 && index <= fPictureCount);
+ return *fPictureRefs[index - 1];
+ }
+
+ const SkPaint* getPaint() {
+ int index = getInt();
+ if (index == 0) {
+ return NULL;
+ }
+ SkASSERT(index > 0 && index <= fPaintCount);
+ return &fPaints[index - 1];
+ }
+
+ const SkRect* getRectPtr() {
+ if (fReader.readBool()) {
+ return fReader.skipRect();
+ } else {
+ return NULL;
+ }
+ }
+
+ const SkIRect* getIRectPtr() {
+ if (fReader.readBool()) {
+ return (const SkIRect*)fReader.skip(sizeof(SkIRect));
+ } else {
+ return NULL;
+ }
+ }
+
+ const SkRegion& getRegion() {
+ int index = getInt();
+ SkASSERT(index > 0);
+ return fRegions[index - 1];
+ }
+
+ SkScalar getScalar() { return fReader.readScalar(); }
+
+ void getText(TextContainer* text) {
+ size_t length = text->fByteLength = getInt();
+ text->fText = (const char*)fReader.skip(length);
+ }
+
+ void init();
+
+#ifdef SK_DEBUG_SIZE
+public:
+ int size(size_t* sizePtr);
+ int bitmaps(size_t* size);
+ int paints(size_t* size);
+ int paths(size_t* size);
+ int regions(size_t* size);
+#endif
+
+#ifdef SK_DEBUG_DUMP
+private:
+ void dumpBitmap(const SkBitmap& bitmap) const;
+ void dumpMatrix(const SkMatrix& matrix) const;
+ void dumpPaint(const SkPaint& paint) const;
+ void dumpPath(const SkPath& path) const;
+ void dumpPicture(const SkPicture& picture) const;
+ void dumpRegion(const SkRegion& region) const;
+ int dumpDrawType(char* bufferPtr, char* buffer, DrawType drawType);
+ int dumpInt(char* bufferPtr, char* buffer, char* name);
+ int dumpRect(char* bufferPtr, char* buffer, char* name);
+ int dumpPoint(char* bufferPtr, char* buffer, char* name);
+ void dumpPointArray(char** bufferPtrPtr, char* buffer, int count);
+ int dumpPtr(char* bufferPtr, char* buffer, char* name, void* ptr);
+ int dumpRectPtr(char* bufferPtr, char* buffer, char* name);
+ int dumpScalar(char* bufferPtr, char* buffer, char* name);
+ void dumpText(char** bufferPtrPtr, char* buffer);
+ void dumpStream();
+
+public:
+ void dump() const;
+#endif
+
+private:
+ SkBitmap* fBitmaps;
+ int fBitmapCount;
+ SkMatrix* fMatrices;
+ int fMatrixCount;
+ SkPaint* fPaints;
+ int fPaintCount;
+ SkPath* fPaths;
+ int fPathCount;
+ SkRegion* fRegions;
+ int fRegionCount;
+ mutable SkFlattenableReadBuffer fReader;
+
+ SkPicture** fPictureRefs;
+ int fPictureCount;
+
+ SkRefCntPlayback fRCPlayback;
+ SkTypefacePlayback fTFPlayback;
+ SkFactoryPlayback* fFactoryPlayback;
+};
+
+#endif
diff --git a/skia/picture/SkPictureRecord.cpp b/skia/picture/SkPictureRecord.cpp
new file mode 100644
index 0000000..718526b
--- /dev/null
+++ b/skia/picture/SkPictureRecord.cpp
@@ -0,0 +1,688 @@
+#include "SkPictureRecord.h"
+#include "SkTSearch.h"
+
+#define MIN_WRITER_SIZE 16384
+#define HEAP_BLOCK_SIZE 4096
+
+SkPictureRecord::SkPictureRecord() :
+ fHeap(HEAP_BLOCK_SIZE), fWriter(MIN_WRITER_SIZE) {
+ fBitmapIndex = fMatrixIndex = fPaintIndex = fPathIndex = fRegionIndex = 1;
+#ifdef SK_DEBUG_SIZE
+ fPointBytes = fRectBytes = fTextBytes = 0;
+ fPointWrites = fRectWrites = fTextWrites = 0;
+#endif
+
+ fRestoreOffsetStack.setReserve(32);
+ fRestoreOffsetStack.push(0);
+}
+
+SkPictureRecord::~SkPictureRecord() {
+ reset();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+int SkPictureRecord::save(SaveFlags flags) {
+ addDraw(SAVE);
+ addInt(flags);
+
+ fRestoreOffsetStack.push(0);
+
+ validate();
+ return this->INHERITED::save(flags);
+}
+
+int SkPictureRecord::saveLayer(const SkRect* bounds, const SkPaint* paint,
+ SaveFlags flags) {
+ addDraw(SAVE_LAYER);
+ addRectPtr(bounds);
+ addPaintPtr(paint);
+ addInt(flags);
+
+ fRestoreOffsetStack.push(0);
+
+ validate();
+ return this->INHERITED::saveLayer(bounds, paint, flags);
+}
+
+void SkPictureRecord::restore() {
+
+ // patch up the clip offsets
+ {
+ uint32_t restoreOffset = (uint32_t)fWriter.size();
+ uint32_t offset = fRestoreOffsetStack.top();
+ while (offset) {
+ uint32_t* peek = fWriter.peek32(offset);
+ offset = *peek;
+ *peek = restoreOffset;
+ }
+ fRestoreOffsetStack.pop();
+ }
+
+ addDraw(RESTORE);
+ validate();
+ return this->INHERITED::restore();
+}
+
+bool SkPictureRecord::translate(SkScalar dx, SkScalar dy) {
+ addDraw(TRANSLATE);
+ addScalar(dx);
+ addScalar(dy);
+ validate();
+ return this->INHERITED::translate(dx, dy);
+}
+
+bool SkPictureRecord::scale(SkScalar sx, SkScalar sy) {
+ addDraw(SCALE);
+ addScalar(sx);
+ addScalar(sy);
+ validate();
+ return this->INHERITED::scale(sx, sy);
+}
+
+bool SkPictureRecord::rotate(SkScalar degrees) {
+ addDraw(ROTATE);
+ addScalar(degrees);
+ validate();
+ return this->INHERITED::rotate(degrees);
+}
+
+bool SkPictureRecord::skew(SkScalar sx, SkScalar sy) {
+ addDraw(SKEW);
+ addScalar(sx);
+ addScalar(sy);
+ validate();
+ return this->INHERITED::skew(sx, sy);
+}
+
+bool SkPictureRecord::concat(const SkMatrix& matrix) {
+ validate();
+ addDraw(CONCAT);
+ addMatrix(matrix);
+ validate();
+ return this->INHERITED::concat(matrix);
+}
+
+bool SkPictureRecord::clipRect(const SkRect& rect, SkRegion::Op op) {
+ addDraw(CLIP_RECT);
+ addRect(rect);
+ addInt(op);
+
+ size_t offset = fWriter.size();
+ addInt(fRestoreOffsetStack.top());
+ fRestoreOffsetStack.top() = offset;
+
+ validate();
+ return this->INHERITED::clipRect(rect, op);
+}
+
+bool SkPictureRecord::clipPath(const SkPath& path, SkRegion::Op op) {
+ addDraw(CLIP_PATH);
+ addPath(path);
+ addInt(op);
+
+ size_t offset = fWriter.size();
+ addInt(fRestoreOffsetStack.top());
+ fRestoreOffsetStack.top() = offset;
+
+ validate();
+ return this->INHERITED::clipPath(path, op);
+}
+
+bool SkPictureRecord::clipRegion(const SkRegion& region, SkRegion::Op op) {
+ addDraw(CLIP_REGION);
+ addRegion(region);
+ addInt(op);
+
+ size_t offset = fWriter.size();
+ addInt(fRestoreOffsetStack.top());
+ fRestoreOffsetStack.top() = offset;
+
+ validate();
+ return this->INHERITED::clipRegion(region, op);
+}
+
+void SkPictureRecord::drawPaint(const SkPaint& paint) {
+ addDraw(DRAW_PAINT);
+ addPaint(paint);
+ validate();
+}
+
+void SkPictureRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
+ const SkPaint& paint) {
+ addDraw(DRAW_POINTS);
+ addPaint(paint);
+ addInt(mode);
+ addInt(count);
+ fWriter.writeMul4(pts, count * sizeof(SkPoint));
+ validate();
+}
+
+// return true if geometry drawn with this paint will just be filled
+// i.e. its bounding rect will not be larger than the original geometry
+static bool is_simple_fill(const SkPaint& paint) {
+ return paint.getStyle() == SkPaint::kFill_Style &&
+ paint.getPathEffect() == NULL &&
+ paint.getMaskFilter() == NULL &&
+ paint.getRasterizer() == NULL;
+}
+
+void SkPictureRecord::drawRect(const SkRect& rect, const SkPaint& paint) {
+ addDraw(is_simple_fill(paint) ? DRAW_RECT_SIMPLE : DRAW_RECT_GENERAL);
+ addPaint(paint);
+ addRect(rect);
+ validate();
+}
+
+void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) {
+ addDraw(DRAW_PATH);
+ addPaint(paint);
+ addPath(path);
+ validate();
+}
+
+void SkPictureRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
+ const SkPaint* paint = NULL) {
+ addDraw(DRAW_BITMAP);
+ addPaintPtr(paint);
+ addBitmap(bitmap);
+ addScalar(left);
+ addScalar(top);
+ validate();
+}
+
+void SkPictureRecord::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
+ const SkRect& dst, const SkPaint* paint) {
+ addDraw(DRAW_BITMAP_RECT);
+ addPaintPtr(paint);
+ addBitmap(bitmap);
+ addIRectPtr(src); // may be null
+ addRect(dst);
+ validate();
+}
+
+void SkPictureRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
+ const SkPaint* paint) {
+ addDraw(DRAW_BITMAP_MATRIX);
+ addPaintPtr(paint);
+ addBitmap(bitmap);
+ addMatrix(matrix);
+ validate();
+}
+
+void SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
+ const SkPaint* paint = NULL) {
+ addDraw(DRAW_SPRITE);
+ addPaintPtr(paint);
+ addBitmap(bitmap);
+ addInt(left);
+ addInt(top);
+ validate();
+}
+
+void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint,
+ SkScalar baselineY) {
+ SkPaint::FontMetrics metrics;
+ paint.getFontMetrics(&metrics);
+ addScalar(metrics.fTop + baselineY);
+ addScalar(metrics.fBottom + baselineY);
+}
+
+void SkPictureRecord::drawText(const void* text, size_t byteLength, SkScalar x,
+ SkScalar y, const SkPaint& paint) {
+ addDraw(DRAW_TEXT);
+ addPaint(paint);
+ addText(text, byteLength);
+ addScalar(x);
+ addScalar(y);
+ addFontMetricsTopBottom(paint, y);
+ validate();
+}
+
+void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
+ const SkPoint pos[], const SkPaint& paint) {
+ size_t points = paint.countText(text, byteLength);
+ if (0 == points)
+ return;
+
+ bool canUseDrawH = true;
+ // check if the caller really should have used drawPosTextH()
+ {
+ const SkScalar firstY = pos[0].fY;
+ for (size_t index = 1; index < points; index++) {
+ if (pos[index].fY != firstY) {
+ canUseDrawH = false;
+ break;
+ }
+ }
+ }
+
+ addDraw(canUseDrawH ? DRAW_POS_TEXT_H : DRAW_POS_TEXT);
+ addPaint(paint);
+ addText(text, byteLength);
+ addInt(points);
+
+#ifdef SK_DEBUG_SIZE
+ size_t start = fWriter.size();
+#endif
+ if (canUseDrawH) {
+ addFontMetricsTopBottom(paint, pos[0].fY);
+ addScalar(pos[0].fY);
+ SkScalar* xptr = (SkScalar*)fWriter.reserve(points * sizeof(SkScalar));
+ for (size_t index = 0; index < points; index++)
+ *xptr++ = pos[index].fX;
+ }
+ else {
+ fWriter.writeMul4(pos, points * sizeof(SkPoint));
+ }
+#ifdef SK_DEBUG_SIZE
+ fPointBytes += fWriter.size() - start;
+ fPointWrites += points;
+#endif
+ validate();
+}
+
+void SkPictureRecord::drawPosTextH(const void* text, size_t byteLength,
+ const SkScalar xpos[], SkScalar constY,
+ const SkPaint& paint) {
+ size_t points = paint.countText(text, byteLength);
+ if (0 == points)
+ return;
+
+ addDraw(DRAW_POS_TEXT_H);
+ addPaint(paint);
+ addText(text, byteLength);
+ addInt(points);
+
+#ifdef SK_DEBUG_SIZE
+ size_t start = fWriter.size();
+#endif
+ addFontMetricsTopBottom(paint, constY);
+ addScalar(constY);
+ fWriter.writeMul4(xpos, points * sizeof(SkScalar));
+#ifdef SK_DEBUG_SIZE
+ fPointBytes += fWriter.size() - start;
+ fPointWrites += points;
+#endif
+ validate();
+}
+
+void SkPictureRecord::drawTextOnPath(const void* text, size_t byteLength,
+ const SkPath& path, const SkMatrix* matrix,
+ const SkPaint& paint) {
+ addDraw(DRAW_TEXT_ON_PATH);
+ addPaint(paint);
+ addText(text, byteLength);
+ addPath(path);
+ addMatrixPtr(matrix);
+ validate();
+}
+
+void SkPictureRecord::drawPicture(SkPicture& picture) {
+ addDraw(DRAW_PICTURE);
+ addPicture(picture);
+ validate();
+}
+
+void SkPictureRecord::drawVertices(VertexMode vmode, int vertexCount,
+ const SkPoint vertices[], const SkPoint texs[],
+ const SkColor colors[], SkXfermode*,
+ const uint16_t indices[], int indexCount,
+ const SkPaint& paint) {
+ uint32_t flags = 0;
+ if (texs) {
+ flags |= DRAW_VERTICES_HAS_TEXS;
+ }
+ if (colors) {
+ flags |= DRAW_VERTICES_HAS_COLORS;
+ }
+ if (indexCount > 0) {
+ flags |= DRAW_VERTICES_HAS_INDICES;
+ }
+
+ addDraw(DRAW_VERTICES);
+ addPaint(paint);
+ addInt(flags);
+ addInt(vmode);
+ addInt(vertexCount);
+ addPoints(vertices, vertexCount);
+ if (flags & DRAW_VERTICES_HAS_TEXS) {
+ addPoints(texs, vertexCount);
+ }
+ if (flags & DRAW_VERTICES_HAS_COLORS) {
+ fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
+ }
+ if (flags & DRAW_VERTICES_HAS_INDICES) {
+ addInt(indexCount);
+ fWriter.writePad(indices, indexCount * sizeof(uint16_t));
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SkPictureRecord::reset() {
+ fBitmaps.reset();
+ fMatrices.reset();
+ fPaints.reset();
+ fPaths.reset();
+ fPictureRefs.unrefAll();
+ fRegions.reset();
+ fWriter.reset();
+ fHeap.reset();
+
+ fRestoreOffsetStack.setCount(1);
+ fRestoreOffsetStack.top() = 0;
+
+ fRCRecorder.reset();
+ fTFRecorder.reset();
+}
+
+void SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
+ addInt(find(fBitmaps, bitmap));
+}
+
+void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
+ addMatrixPtr(&matrix);
+}
+
+void SkPictureRecord::addMatrixPtr(const SkMatrix* matrix) {
+ addInt(find(fMatrices, matrix));
+}
+
+void SkPictureRecord::addPaint(const SkPaint& paint) {
+ addPaintPtr(&paint);
+}
+
+void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
+ addInt(find(fPaints, paint));
+}
+
+void SkPictureRecord::addPath(const SkPath& path) {
+ addInt(find(fPaths, path));
+}
+
+void SkPictureRecord::addPicture(SkPicture& picture) {
+ int index = fPictureRefs.find(&picture);
+ if (index < 0) { // not found
+ index = fPictureRefs.count();
+ *fPictureRefs.append() = &picture;
+ picture.ref();
+ }
+ // follow the convention of recording a 1-based index
+ addInt(index + 1);
+}
+
+void SkPictureRecord::addPoint(const SkPoint& point) {
+#ifdef SK_DEBUG_SIZE
+ size_t start = fWriter.size();
+#endif
+ fWriter.writePoint(point);
+#ifdef SK_DEBUG_SIZE
+ fPointBytes += fWriter.size() - start;
+ fPointWrites++;
+#endif
+}
+
+void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
+ fWriter.writeMul4(pts, count * sizeof(SkPoint));
+#ifdef SK_DEBUG_SIZE
+ fPointBytes += count * sizeof(SkPoint);
+ fPointWrites++;
+#endif
+}
+
+void SkPictureRecord::addRect(const SkRect& rect) {
+#ifdef SK_DEBUG_SIZE
+ size_t start = fWriter.size();
+#endif
+ fWriter.writeRect(rect);
+#ifdef SK_DEBUG_SIZE
+ fRectBytes += fWriter.size() - start;
+ fRectWrites++;
+#endif
+}
+
+void SkPictureRecord::addRectPtr(const SkRect* rect) {
+ if (fWriter.writeBool(rect != NULL)) {
+ fWriter.writeRect(*rect);
+ }
+}
+
+void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
+ if (fWriter.writeBool(rect != NULL)) {
+ *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
+ }
+}
+
+void SkPictureRecord::addRegion(const SkRegion& region) {
+ addInt(find(fRegions, region));
+}
+
+void SkPictureRecord::addText(const void* text, size_t byteLength) {
+#ifdef SK_DEBUG_SIZE
+ size_t start = fWriter.size();
+#endif
+ addInt(byteLength);
+ fWriter.writePad(text, byteLength);
+#ifdef SK_DEBUG_SIZE
+ fTextBytes += fWriter.size() - start;
+ fTextWrites++;
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+int SkPictureRecord::find(SkTDArray<const SkFlatBitmap* >& bitmaps, const SkBitmap& bitmap) {
+ SkFlatBitmap* flat = SkFlatBitmap::Flatten(&fHeap, bitmap, fBitmapIndex,
+ &fRCRecorder);
+ int index = SkTSearch<SkFlatData>((const SkFlatData**) bitmaps.begin(),
+ bitmaps.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
+ if (index >= 0) {
+// SkBitmap bitmap;
+// flat->unflatten(&bitmap); // balance ref count
+ 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)
+ 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,
+ &fRCRecorder, &fTFRecorder);
+ int index = SkTSearch<SkFlatData>((const SkFlatData**) paints.begin(),
+ paints.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
+ if (index >= 0) {
+ return paints[index]->index();
+ }
+
+ index = ~index;
+ *paints.insert(index) = flat;
+ return fPaintIndex++;
+}
+
+int SkPictureRecord::find(SkTDArray<const SkFlatPath* >& paths, const SkPath& path) {
+ SkFlatPath* flat = SkFlatPath::Flatten(&fHeap, path, fPathIndex);
+ int index = SkTSearch<SkFlatData>((const SkFlatData**) paths.begin(),
+ paths.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
+ if (index >= 0)
+ return paths[index]->index();
+ index = ~index;
+ *paths.insert(index) = flat;
+ return fPathIndex++;
+}
+
+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)
+ 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;
+ size_t sizeData;
+ bitmaps(&sizeData);
+ result += sizeData;
+ matrices(&sizeData);
+ result += sizeData;
+ paints(&sizeData);
+ result += sizeData;
+ paths(&sizeData);
+ result += sizeData;
+ pictures(&sizeData);
+ result += sizeData;
+ regions(&sizeData);
+ result += sizeData;
+ result += streamlen();
+ return result;
+}
+
+int SkPictureRecord::bitmaps(size_t* size) const {
+ size_t result = 0;
+ int count = fBitmaps.count();
+ for (int index = 0; index < count; index++)
+ result += sizeof(fBitmaps[index]) + fBitmaps[index]->size();
+ *size = result;
+ return count;
+}
+
+int SkPictureRecord::matrices(size_t* size) const {
+ int count = fMatrices.count();
+ *size = sizeof(fMatrices[0]) * count;
+ return count;
+}
+
+int SkPictureRecord::paints(size_t* size) const {
+ size_t result = 0;
+ int count = fPaints.count();
+ for (int index = 0; index < count; index++)
+ result += sizeof(fPaints[index]) + fPaints[index]->size();
+ *size = result;
+ return count;
+}
+
+int SkPictureRecord::paths(size_t* size) const {
+ size_t result = 0;
+ int count = fPaths.count();
+ for (int index = 0; index < count; index++)
+ result += sizeof(fPaths[index]) + fPaths[index]->size();
+ *size = result;
+ return count;
+}
+
+int SkPictureRecord::regions(size_t* size) const {
+ size_t result = 0;
+ int count = fRegions.count();
+ for (int index = 0; index < count; index++)
+ result += sizeof(fRegions[index]) + fRegions[index]->size();
+ *size = result;
+ return count;
+}
+
+size_t SkPictureRecord::streamlen() const {
+ return fWriter.size();
+}
+#endif
+
+#ifdef SK_DEBUG_VALIDATE
+void SkPictureRecord::validate() const {
+ validateBitmaps();
+ validateMatrices();
+ validatePaints();
+ validatePaths();
+ validatePictures();
+ validateRegions();
+}
+
+void SkPictureRecord::validateBitmaps() const {
+ int count = fBitmaps.count();
+ SkASSERT((unsigned) count < 0x1000);
+ for (int index = 0; index < count; index++) {
+ const SkFlatBitmap* bitPtr = fBitmaps[index];
+ SkASSERT(bitPtr);
+ bitPtr->validate();
+ }
+}
+
+void SkPictureRecord::validateMatrices() const {
+ int count = fMatrices.count();
+ SkASSERT((unsigned) count < 0x1000);
+ for (int index = 0; index < count; index++) {
+ const SkFlatMatrix* matrix = fMatrices[index];
+ SkASSERT(matrix);
+ matrix->validate();
+ }
+}
+
+void SkPictureRecord::validatePaints() const {
+ int count = fPaints.count();
+ SkASSERT((unsigned) count < 0x1000);
+ for (int index = 0; index < count; index++) {
+ const SkFlatPaint* paint = fPaints[index];
+ SkASSERT(paint);
+// paint->validate();
+ }
+}
+
+void SkPictureRecord::validatePaths() const {
+ int count = fPaths.count();
+ SkASSERT((unsigned) count < 0x1000);
+ for (int index = 0; index < count; index++) {
+ const SkFlatPath* path = fPaths[index];
+ SkASSERT(path);
+ path->validate();
+ }
+}
+
+void SkPictureRecord::validateRegions() const {
+ int count = fRegions.count();
+ SkASSERT((unsigned) count < 0x1000);
+ for (int index = 0; index < count; index++) {
+ const SkFlatRegion* region = fRegions[index];
+ SkASSERT(region);
+ region->validate();
+ }
+}
+#endif
+
diff --git a/skia/picture/SkPictureRecord.h b/skia/picture/SkPictureRecord.h
new file mode 100644
index 0000000..350040e
--- /dev/null
+++ b/skia/picture/SkPictureRecord.h
@@ -0,0 +1,182 @@
+#ifndef SkPictureRecord_DEFINED
+#define SkPictureRecord_DEFINED
+
+#include "SkCanvas.h"
+#include "SkFlattenable.h"
+#include "SkPicture.h"
+#include "SkPictureFlat.h"
+#include "SkTemplates.h"
+#include "SkWriter32.h"
+
+class SkPictureRecord : public SkCanvas {
+public:
+ SkPictureRecord();
+ virtual ~SkPictureRecord();
+
+ // overrides from SkCanvas
+ virtual int save(SaveFlags);
+ virtual int saveLayer(const SkRect* bounds, const SkPaint*, SaveFlags);
+ virtual void restore();
+ virtual bool translate(SkScalar dx, SkScalar dy);
+ virtual bool scale(SkScalar sx, SkScalar sy);
+ virtual bool rotate(SkScalar degrees);
+ virtual bool skew(SkScalar sx, SkScalar sy);
+ virtual bool concat(const SkMatrix& matrix);
+ virtual bool clipRect(const SkRect& rect, SkRegion::Op op);
+ virtual bool clipPath(const SkPath& path, SkRegion::Op op);
+ virtual bool clipRegion(const SkRegion& region, SkRegion::Op op);
+ virtual void drawPaint(const SkPaint& paint);
+ virtual void drawPoints(PointMode, size_t count, const SkPoint pts[],
+ const SkPaint&);
+ virtual void drawRect(const SkRect& rect, const SkPaint&);
+ virtual void drawPath(const SkPath& path, const SkPaint&);
+ virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
+ const SkPaint*);
+ virtual void drawBitmapRect(const SkBitmap&, const SkIRect* src,
+ const SkRect& dst, const SkPaint*);
+ virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
+ const SkPaint*);
+ virtual void drawSprite(const SkBitmap&, int left, int top,
+ const SkPaint*);
+ virtual void drawText(const void* text, size_t byteLength, SkScalar x,
+ SkScalar y, const SkPaint&);
+ virtual void drawPosText(const void* text, size_t byteLength,
+ const SkPoint pos[], const SkPaint&);
+ virtual void drawPosTextH(const void* text, size_t byteLength,
+ const SkScalar xpos[], SkScalar constY, const SkPaint&);
+ virtual void drawTextOnPath(const void* text, size_t byteLength,
+ const SkPath& path, const SkMatrix* matrix,
+ const SkPaint&);
+ virtual void drawPicture(SkPicture& picture);
+ virtual void drawVertices(VertexMode, int vertexCount,
+ const SkPoint vertices[], const SkPoint texs[],
+ const SkColor colors[], SkXfermode*,
+ const uint16_t indices[], int indexCount,
+ const SkPaint&);
+
+ void addFontMetricsTopBottom(const SkPaint& paint, SkScalar baselineY);
+
+ const SkTDArray<const SkFlatBitmap* >& getBitmaps() const {
+ return fBitmaps;
+ }
+ const SkTDArray<const SkFlatMatrix* >& getMatrices() const {
+ return fMatrices;
+ }
+ const SkTDArray<const SkFlatPaint* >& getPaints() const {
+ return fPaints;
+ }
+ const SkTDArray<const SkFlatPath* >& getPaths() const {
+ return fPaths;
+ }
+ const SkTDArray<SkPicture* >& getPictureRefs() const {
+ return fPictureRefs;
+ }
+ const SkTDArray<const SkFlatRegion* >& getRegions() const {
+ return fRegions;
+ }
+
+ void reset();
+
+ const SkWriter32& writeStream() const {
+ return fWriter;
+ }
+
+private:
+ SkTDArray<uint32_t> fRestoreOffsetStack;
+
+ void addDraw(DrawType drawType) {
+#ifdef SK_DEBUG_TRACE
+ SkDebugf("add %s\n", DrawTypeToString(drawType));
+#endif
+ fWriter.writeInt(drawType);
+ }
+ void addInt(int value) {
+ fWriter.writeInt(value);
+ }
+ void addScalar(SkScalar scalar) {
+ fWriter.writeScalar(scalar);
+ }
+
+ void addBitmap(const SkBitmap& bitmap);
+ void addMatrix(const SkMatrix& matrix);
+ void addMatrixPtr(const SkMatrix* matrix);
+ void addPaint(const SkPaint& paint);
+ void addPaintPtr(const SkPaint* paint);
+ void addPath(const SkPath& path);
+ void addPicture(SkPicture& picture);
+ void addPoint(const SkPoint& point);
+ void addPoints(const SkPoint pts[], int count);
+ void addRect(const SkRect& rect);
+ void addRectPtr(const SkRect* rect);
+ void addIRectPtr(const SkIRect* rect);
+ 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 SkFlatPath* >& paths, const SkPath& path);
+ int find(SkTDArray<const SkFlatRegion* >& regions, const SkRegion& region);
+
+#ifdef SK_DEBUG_DUMP
+public:
+ void dumpMatrices();
+ void dumpPaints();
+#endif
+
+#ifdef SK_DEBUG_SIZE
+public:
+ size_t size() const;
+ int bitmaps(size_t* size) const;
+ int matrices(size_t* size) const;
+ int paints(size_t* size) const;
+ int paths(size_t* size) const;
+ int regions(size_t* size) const;
+ size_t streamlen() const;
+
+ size_t fPointBytes, fRectBytes, fTextBytes;
+ int fPointWrites, fRectWrites, fTextWrites;
+#endif
+
+#ifdef SK_DEBUG_VALIDATE
+public:
+ void validate() const;
+private:
+ void validateBitmaps() const;
+ void validateMatrices() const;
+ void validatePaints() const;
+ void validatePaths() const;
+ void validateRegions() const;
+#else
+public:
+ void validate() const {}
+#endif
+
+private:
+ SkChunkAlloc fHeap;
+ int fBitmapIndex;
+ SkTDArray<const SkFlatBitmap* > fBitmaps;
+ int fMatrixIndex;
+ SkTDArray<const SkFlatMatrix* > fMatrices;
+ int fPaintIndex;
+ SkTDArray<const SkFlatPaint* > fPaints;
+ int fPathIndex;
+ SkTDArray<const SkFlatPath* > fPaths;
+ int fRegionIndex;
+ SkTDArray<const SkFlatRegion* > fRegions;
+ SkWriter32 fWriter;
+
+ // we ref each item in this array
+ SkTDArray<SkPicture*> fPictureRefs;
+
+ SkRefCntRecorder fRCRecorder;
+ SkRefCntRecorder fTFRecorder;
+
+ friend class SkPicturePlayback;
+
+ typedef SkCanvas INHERITED;
+};
+
+#endif