diff options
author | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-27 00:09:42 +0000 |
---|---|---|
committer | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-27 00:09:42 +0000 |
commit | ae2c20f398933a9e86c387dcc465ec0f71065ffc (patch) | |
tree | de668b1411e2ee0b4e49b6d8f8b68183134ac990 /skia/picture | |
parent | 09911bf300f1a419907a9412154760efd0b7abc3 (diff) | |
download | chromium_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.cpp | 266 | ||||
-rw-r--r-- | skia/picture/SkPictureFlat.h | 225 | ||||
-rw-r--r-- | skia/picture/SkPicturePlayback.cpp | 1366 | ||||
-rw-r--r-- | skia/picture/SkPicturePlayback.h | 166 | ||||
-rw-r--r-- | skia/picture/SkPictureRecord.cpp | 688 | ||||
-rw-r--r-- | skia/picture/SkPictureRecord.h | 182 |
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(®ionBytes); + 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(®ionBytes); + 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 |