From 8f831f262f5e57665587cb3033860eea39fe1621 Mon Sep 17 00:00:00 2001 From: "commit-bot@chromium.org" Date: Wed, 23 Apr 2014 22:35:42 +0000 Subject: [PATCH] First step in pulling SkPicturePlayback & SkPictureRecord out of SkPicture This CL begins the process of making SkPicturePlayback & SkPictureRecord independent of SkPicture. It just moves the PathHeap into SkPicture to get a feel for where all this is going to lead. Some items of note: SkTimedPicture (debugger/QT) should wind up being just an SkPicturePlayback-derived object. All the flattening & unflattening should migrate out of SkPicturePlayback and into SkPicture. SkPicture::initForPlayback should eventually become something just SkPictureRecorder::endRecording calls. SkPicture is passed into SkPicturePlayback's & SkPictureRecord's constructors. SkPicturePlayback only holds onto a "const SkPicture*". The SkPicturePlayback:: CreateFromStream & CreateFromBuffer methods pass a non-const SkPicture* down the call stack. BUG=skia:2315 R=reed@google.com Author: robertphillips@google.com Review URL: https://codereview.chromium.org/249453002 git-svn-id: http://skia.googlecode.com/svn/trunk@14341 2bbb7eff-a529-9590-31e7-b0007b416f81 --- debugger/QT/SkDebuggerGUI.cpp | 25 ++++---- include/core/SkPicture.h | 18 ++++++ src/core/SkBBoxHierarchyRecord.cpp | 5 +- src/core/SkBBoxHierarchyRecord.h | 3 +- src/core/SkBBoxRecord.h | 4 +- src/core/SkPicture.cpp | 116 +++++++++++++++++++++++++++++++------ src/core/SkPicturePlayback.cpp | 107 +++++++++++++++------------------- src/core/SkPicturePlayback.h | 33 +++++++---- src/core/SkPictureRecord.cpp | 14 +---- src/core/SkPictureRecord.h | 6 +- tests/CanvasTest.cpp | 4 +- 11 files changed, 217 insertions(+), 118 deletions(-) diff --git a/debugger/QT/SkDebuggerGUI.cpp b/debugger/QT/SkDebuggerGUI.cpp index 0572550..b476a14 100644 --- a/debugger/QT/SkDebuggerGUI.cpp +++ b/debugger/QT/SkDebuggerGUI.cpp @@ -159,20 +159,23 @@ void SkDebuggerGUI::showDeletes() { // offsets to individual commands. class SkTimedPicturePlayback : public SkPicturePlayback { public: - static SkTimedPicturePlayback* CreateFromStream(SkStream* stream, const SkPictInfo& info, + static SkTimedPicturePlayback* CreateFromStream(SkPicture* picture, + SkStream* stream, const SkPictInfo& info, SkPicture::InstallPixelRefProc proc, const SkTDArray& deletedCommands) { // Mimics SkPicturePlayback::CreateFromStream SkAutoTDelete playback(SkNEW_ARGS(SkTimedPicturePlayback, - (deletedCommands, info))); - if (!playback->parseStream(stream, proc)) { + (picture, deletedCommands, info))); + if (!playback->parseStream(picture, stream, proc)) { return NULL; // we're invalid } return playback.detach(); } - SkTimedPicturePlayback(const SkTDArray& deletedCommands, const SkPictInfo& info) - : INHERITED(info) + SkTimedPicturePlayback(SkPicture* picture, + const SkTDArray& deletedCommands, + const SkPictInfo& info) + : INHERITED(picture, info) , fSkipCommands(deletedCommands) , fTot(0.0) , fCurCommand(0) { @@ -268,19 +271,21 @@ public: return NULL; } - SkTimedPicturePlayback* playback; + SkTimedPicture* newPict = SkNEW_ARGS(SkTimedPicture, (NULL, info.fWidth, info.fHeight)); // Check to see if there is a playback to recreate. if (stream->readBool()) { - playback = SkTimedPicturePlayback::CreateFromStream(stream, info, proc, + SkTimedPicturePlayback* playback = SkTimedPicturePlayback::CreateFromStream( + newPict, stream, + info, proc, deletedCommands); if (NULL == playback) { + SkDELETE(newPict); return NULL; } - } else { - playback = NULL; + newPict->fPlayback = playback; } - return SkNEW_ARGS(SkTimedPicture, (playback, info.fWidth, info.fHeight)); + return newPict; } void resetTimes() { ((SkTimedPicturePlayback*) fPlayback)->resetTimes(); } diff --git a/include/core/SkPicture.h b/include/core/SkPicture.h index 996d857..e44f697 100644 --- a/include/core/SkPicture.h +++ b/include/core/SkPicture.h @@ -23,6 +23,7 @@ class SkBBoxHierarchy; class SkCanvas; class SkDrawPictureCallback; class SkData; +class SkPathHeap; class SkPicturePlayback; class SkPictureRecord; class SkStream; @@ -358,6 +359,23 @@ protected: SkCanvas* beginRecording(int width, int height, SkBBHFactory* factory, uint32_t recordFlags); private: + friend class SkPictureRecord; + friend class SkPictureTester; // for unit testing + + SkAutoTUnref fPathHeap; // reference counted + + const SkPath& getPath(int index) const; + int addPathToHeap(const SkPath& path); + + void flattenToBuffer(SkWriteBuffer& buffer) const; + bool parseBufferTag(SkReadBuffer& buffer, uint32_t tag, uint32_t size); + + static void WriteTagSize(SkWriteBuffer& buffer, uint32_t tag, size_t size); + static void WriteTagSize(SkWStream* stream, uint32_t tag, size_t size); + + void initForPlayback() const; + void dumpSize() const; + // An OperationList encapsulates a set of operation offsets into the picture byte // stream along with the CTMs needed for those operation. class OperationList : ::SkNoncopyable { diff --git a/src/core/SkBBoxHierarchyRecord.cpp b/src/core/SkBBoxHierarchyRecord.cpp index 16ade77..f0382e6 100644 --- a/src/core/SkBBoxHierarchyRecord.cpp +++ b/src/core/SkBBoxHierarchyRecord.cpp @@ -9,10 +9,11 @@ #include "SkBBoxHierarchyRecord.h" #include "SkPictureStateTree.h" -SkBBoxHierarchyRecord::SkBBoxHierarchyRecord(const SkISize& size, +SkBBoxHierarchyRecord::SkBBoxHierarchyRecord(SkPicture* picture, + const SkISize& size, uint32_t recordFlags, SkBBoxHierarchy* h) - : INHERITED(size, recordFlags) { + : INHERITED(picture, size, recordFlags) { fStateTree = SkNEW(SkPictureStateTree); fBoundingHierarchy = h; fBoundingHierarchy->ref(); diff --git a/src/core/SkBBoxHierarchyRecord.h b/src/core/SkBBoxHierarchyRecord.h index 51fce0d..aa8b70a 100644 --- a/src/core/SkBBoxHierarchyRecord.h +++ b/src/core/SkBBoxHierarchyRecord.h @@ -19,7 +19,8 @@ class SkBBoxHierarchyRecord : public SkBBoxRecord, public SkBBoxHierarchyClient { public: /** This will take a ref of h */ - SkBBoxHierarchyRecord(const SkISize& size, uint32_t recordFlags, SkBBoxHierarchy* h); + SkBBoxHierarchyRecord(SkPicture* picture, const SkISize& size, + uint32_t recordFlags, SkBBoxHierarchy* h); virtual void handleBBox(const SkRect& bounds) SK_OVERRIDE; diff --git a/src/core/SkBBoxRecord.h b/src/core/SkBBoxRecord.h index 3a0c53b..fef4ce6 100644 --- a/src/core/SkBBoxRecord.h +++ b/src/core/SkBBoxRecord.h @@ -19,7 +19,9 @@ class SkBBoxRecord : public SkPictureRecord { public: - SkBBoxRecord(const SkISize& size, uint32_t recordFlags) : INHERITED(size, recordFlags) {} + SkBBoxRecord(SkPicture* picture, const SkISize& size, uint32_t recordFlags) + : INHERITED(picture, size, recordFlags) { + } virtual ~SkBBoxRecord() { } /** diff --git a/src/core/SkPicture.cpp b/src/core/SkPicture.cpp index 316994a..05e5791 100644 --- a/src/core/SkPicture.cpp +++ b/src/core/SkPicture.cpp @@ -31,6 +31,10 @@ #include "GrContext.h" #endif +template int SafeCount(const T* obj) { + return obj ? obj->count() : 0; +} + #define DUMP_BUFFER_SIZE 65536 //#define ENABLE_TIME_DRAW // dumps milliseconds for each draw @@ -139,17 +143,48 @@ SkPicture::SkPicture(const SkPicture& src) it (since it is destructive, and we don't want to change src). */ if (src.fPlayback) { - fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fPlayback)); + fPlayback = SkNEW_ARGS(SkPicturePlayback, (this, *src.fPlayback)); SkASSERT(NULL == src.fRecord); fUniqueID = src.uniqueID(); // need to call method to ensure != 0 } else if (src.fRecord) { SkPictInfo info; this->createHeader(&info); // here we do a fake src.endRecording() - fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fRecord, info)); + fPlayback = SkNEW_ARGS(SkPicturePlayback, (this, *src.fRecord, info)); } else { fPlayback = NULL; } + + fPathHeap.reset(SkSafeRef(src.fPathHeap.get())); +} + +const SkPath& SkPicture::getPath(int index) const { + return (*fPathHeap.get())[index]; +} + +int SkPicture::addPathToHeap(const SkPath& path) { + if (NULL == fPathHeap) { + fPathHeap.reset(SkNEW(SkPathHeap)); + } +#ifdef SK_DEDUP_PICTURE_PATHS + return fPathHeap->insert(path); +#else + return fPathHeap->append(path); +#endif +} + +void SkPicture::initForPlayback() const { + // ensure that the paths bounds are pre-computed + if (NULL != fPathHeap.get()) { + for (int i = 0; i < fPathHeap->count(); i++) { + (*fPathHeap.get())[i].updateBoundsCache(); + } + } +} + +void SkPicture::dumpSize() const { + SkDebugf("--- picture size: paths=%d\n", + SafeCount(fPathHeap.get())); } SkPicture::~SkPicture() { @@ -171,6 +206,7 @@ void SkPicture::swap(SkPicture& other) { SkTSwap(fAccelData, other.fAccelData); SkTSwap(fWidth, other.fWidth); SkTSwap(fHeight, other.fHeight); + fPathHeap.swap(&other.fPathHeap); } SkPicture* SkPicture::clone() const { @@ -198,15 +234,17 @@ void SkPicture::clone(SkPicture* pictures, int count) const { it (since it is destructive, and we don't want to change src). */ if (fPlayback) { - clone->fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fPlayback, ©Info)); + clone->fPlayback = SkNEW_ARGS(SkPicturePlayback, (clone, *fPlayback, ©Info)); SkASSERT(NULL == fRecord); clone->fUniqueID = this->uniqueID(); // need to call method to ensure != 0 } else if (fRecord) { // here we do a fake src.endRecording() - clone->fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fRecord, info, true)); + clone->fPlayback = SkNEW_ARGS(SkPicturePlayback, (clone, *fRecord, info, true)); } else { clone->fPlayback = NULL; } + + clone->fPathHeap.reset(SkSafeRef(fPathHeap.get())); } } @@ -266,6 +304,7 @@ SkCanvas* SkPicture::beginRecording(int width, int height, } SkSafeUnref(fAccelData); SkSafeSetNull(fRecord); + SkASSERT(NULL == fPathHeap); this->needsNewGenID(); @@ -277,12 +316,12 @@ SkCanvas* SkPicture::beginRecording(int width, int height, if (NULL != bbhFactory) { SkAutoTUnref tree((*bbhFactory)(width, height)); SkASSERT(NULL != tree); - fRecord = SkNEW_ARGS(SkBBoxHierarchyRecord, (size, + fRecord = SkNEW_ARGS(SkBBoxHierarchyRecord, (this, size, recordingFlags| kOptimizeForClippedPlayback_RecordingFlag, tree.get())); } else { - fRecord = SkNEW_ARGS(SkPictureRecord, (size, recordingFlags)); + fRecord = SkNEW_ARGS(SkPictureRecord, (this, size, recordingFlags)); } fRecord->beginRecording(); @@ -323,7 +362,7 @@ void SkPicture::endRecording() { fRecord->endRecording(); SkPictInfo info; this->createHeader(&info); - fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fRecord, info)); + fPlayback = SkNEW_ARGS(SkPicturePlayback, (this, *fRecord, info)); SkSafeSetNull(fRecord); } } @@ -424,18 +463,20 @@ SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc pro return NULL; } - SkPicturePlayback* playback; + SkPicture* newPict = SkNEW_ARGS(SkPicture, (NULL, info.fWidth, info.fHeight)); + // Check to see if there is a playback to recreate. if (stream->readBool()) { - playback = SkPicturePlayback::CreateFromStream(stream, info, proc); + SkPicturePlayback* playback = SkPicturePlayback::CreateFromStream(newPict, stream, + info, proc); if (NULL == playback) { + SkDELETE(newPict); return NULL; } - } else { - playback = NULL; + newPict->fPlayback = playback; } - return SkNEW_ARGS(SkPicture, (playback, info.fWidth, info.fHeight)); + return newPict; } SkPicture* SkPicture::CreateFromBuffer(SkReadBuffer& buffer) { @@ -445,18 +486,19 @@ SkPicture* SkPicture::CreateFromBuffer(SkReadBuffer& buffer) { return NULL; } - SkPicturePlayback* playback; + SkPicture* newPict = SkNEW_ARGS(SkPicture, (NULL, info.fWidth, info.fHeight)); + // Check to see if there is a playback to recreate. if (buffer.readBool()) { - playback = SkPicturePlayback::CreateFromBuffer(buffer, info); + SkPicturePlayback* playback = SkPicturePlayback::CreateFromBuffer(newPict, buffer, info); if (NULL == playback) { + SkDELETE(newPict); return NULL; } - } else { - playback = NULL; + newPict->fPlayback = playback; } - return SkNEW_ARGS(SkPicture, (playback, info.fWidth, info.fHeight)); + return newPict; } void SkPicture::createHeader(SkPictInfo* info) const { @@ -484,7 +526,7 @@ void SkPicture::serialize(SkWStream* stream, EncodeBitmap encoder) const { SkPictInfo info; this->createHeader(&info); if (NULL == playback && fRecord) { - playback = SkNEW_ARGS(SkPicturePlayback, (*fRecord, info)); + playback = SkNEW_ARGS(SkPicturePlayback, (this, *fRecord, info)); } stream->write(&info, sizeof(info)); @@ -500,13 +542,49 @@ void SkPicture::serialize(SkWStream* stream, EncodeBitmap encoder) const { } } +void SkPicture::WriteTagSize(SkWriteBuffer& buffer, uint32_t tag, size_t size) { + buffer.writeUInt(tag); + buffer.writeUInt(SkToU32(size)); +} + +void SkPicture::WriteTagSize(SkWStream* stream, uint32_t tag, size_t size) { + stream->write32(tag); + stream->write32(SkToU32(size)); +} + +bool SkPicture::parseBufferTag(SkReadBuffer& buffer, + uint32_t tag, + uint32_t size) { + switch (tag) { + case SK_PICT_PATH_BUFFER_TAG: + if (size > 0) { + fPathHeap.reset(SkNEW_ARGS(SkPathHeap, (buffer))); + } + break; + default: + // The tag was invalid. + return false; + } + + return true; // success +} + +void SkPicture::flattenToBuffer(SkWriteBuffer& buffer) const { + int n; + + if ((n = SafeCount(fPathHeap.get())) > 0) { + WriteTagSize(buffer, SK_PICT_PATH_BUFFER_TAG, n); + fPathHeap->flatten(buffer); + } +} + void SkPicture::flatten(SkWriteBuffer& buffer) const { SkPicturePlayback* playback = fPlayback; SkPictInfo info; this->createHeader(&info); if (NULL == playback && fRecord) { - playback = SkNEW_ARGS(SkPicturePlayback, (*fRecord, info)); + playback = SkNEW_ARGS(SkPicturePlayback, (this, *fRecord, info)); } buffer.writeByteArray(&info, sizeof(info)); diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp index 514769d..5eabb09 100644 --- a/src/core/SkPicturePlayback.cpp +++ b/src/core/SkPicturePlayback.cpp @@ -23,14 +23,18 @@ template int SafeCount(const T* obj) { */ #define SPEW_CLIP_SKIPPINGx -SkPicturePlayback::SkPicturePlayback(const SkPictInfo& info) : fInfo(info) { +SkPicturePlayback::SkPicturePlayback(const SkPicture* picture, const SkPictInfo& info) + : fPicture(picture) + , fInfo(info) { this->init(); } -SkPicturePlayback::SkPicturePlayback(const SkPictureRecord& record, +SkPicturePlayback::SkPicturePlayback(const SkPicture* picture, + const SkPictureRecord& record, const SkPictInfo& info, bool deepCopy) - : fInfo(info) { + : fPicture(picture) + , fInfo(info) { #ifdef SK_DEBUG_SIZE size_t overallBytes, bitmapBytes, matricesBytes, paintBytes, pathBytes, pictureBytes, regionBytes; @@ -95,14 +99,8 @@ SkPicturePlayback::SkPicturePlayback(const SkPictureRecord& record, fPaints = record.fPaints.unflattenToArray(); fBitmapHeap.reset(SkSafeRef(record.fBitmapHeap)); - fPathHeap.reset(SkSafeRef(record.fPathHeap)); - // ensure that the paths bounds are pre-computed - if (fPathHeap.get()) { - for (int i = 0; i < fPathHeap->count(); i++) { - (*fPathHeap)[i].updateBoundsCache(); - } - } + picture->initForPlayback(); const SkTDArray& pictures = record.getPictureRefs(); fPictureCount = pictures.count(); @@ -160,12 +158,13 @@ static bool needs_deep_copy(const SkPaint& paint) { paint.getImageFilter(); } -SkPicturePlayback::SkPicturePlayback(const SkPicturePlayback& src, SkPictCopyInfo* deepCopyInfo) - : fInfo(src.fInfo) { +SkPicturePlayback::SkPicturePlayback(const SkPicture* picture, const SkPicturePlayback& src, + SkPictCopyInfo* deepCopyInfo) + : fPicture(picture) + , fInfo(src.fInfo) { this->init(); fBitmapHeap.reset(SkSafeRef(src.fBitmapHeap.get())); - fPathHeap.reset(SkSafeRef(src.fPathHeap.get())); fOpData = SkSafeRef(src.fOpData); @@ -286,11 +285,11 @@ SkPicturePlayback::~SkPicturePlayback() { } void SkPicturePlayback::dumpSize() const { - SkDebugf("--- picture size: ops=%d bitmaps=%d [%d] paints=%d [%d] paths=%d\n", + SkDebugf("--- picture size: ops=%d bitmaps=%d [%d] paints=%d [%d]\n", fOpData->size(), SafeCount(fBitmaps), SafeCount(fBitmaps) * sizeof(SkBitmap), - SafeCount(fPaints), SafeCount(fPaints) * sizeof(SkPaint), - SafeCount(fPathHeap.get())); + SafeCount(fPaints), SafeCount(fPaints) * sizeof(SkPaint)); + fPicture->dumpSize(); } bool SkPicturePlayback::containsBitmaps() const { @@ -310,16 +309,6 @@ bool SkPicturePlayback::containsBitmaps() const { #include "SkStream.h" -static void write_tag_size(SkWriteBuffer& buffer, uint32_t tag, size_t size) { - buffer.writeUInt(tag); - buffer.writeUInt(SkToU32(size)); -} - -static void write_tag_size(SkWStream* stream, uint32_t tag, size_t size) { - stream->write32(tag); - stream->write32(SkToU32(size)); -} - static size_t compute_chunk_size(SkFlattenable::Factory* array, int count) { size_t size = 4; // for 'count' @@ -337,7 +326,7 @@ static size_t compute_chunk_size(SkFlattenable::Factory* array, int count) { return size; } -static void write_factories(SkWStream* stream, const SkFactorySet& rec) { +void SkPicturePlayback::WriteFactories(SkWStream* stream, const SkFactorySet& rec) { int count = rec.count(); SkAutoSTMalloc<16, SkFlattenable::Factory> storage(count); @@ -347,7 +336,7 @@ static void write_factories(SkWStream* stream, const SkFactorySet& rec) { size_t size = compute_chunk_size(array, count); // TODO: write_tag_size should really take a size_t - write_tag_size(stream, SK_PICT_FACTORY_TAG, (uint32_t) size); + SkPicture::WriteTagSize(stream, SK_PICT_FACTORY_TAG, (uint32_t) size); SkDEBUGCODE(size_t start = stream->bytesWritten()); stream->write32(count); @@ -366,10 +355,10 @@ static void write_factories(SkWStream* stream, const SkFactorySet& rec) { SkASSERT(size == (stream->bytesWritten() - start)); } -static void write_typefaces(SkWStream* stream, const SkRefCntSet& rec) { +void SkPicturePlayback::WriteTypefaces(SkWStream* stream, const SkRefCntSet& rec) { int count = rec.count(); - write_tag_size(stream, SK_PICT_TYPEFACE_TAG, count); + SkPicture::WriteTagSize(stream, SK_PICT_TYPEFACE_TAG, count); SkAutoSTMalloc<16, SkTypeface*> storage(count); SkTypeface** array = (SkTypeface**)storage.get(); @@ -384,32 +373,29 @@ void SkPicturePlayback::flattenToBuffer(SkWriteBuffer& buffer) const { int i, n; if ((n = SafeCount(fBitmaps)) > 0) { - write_tag_size(buffer, SK_PICT_BITMAP_BUFFER_TAG, n); + SkPicture::WriteTagSize(buffer, SK_PICT_BITMAP_BUFFER_TAG, n); for (i = 0; i < n; i++) { buffer.writeBitmap((*fBitmaps)[i]); } } if ((n = SafeCount(fPaints)) > 0) { - write_tag_size(buffer, SK_PICT_PAINT_BUFFER_TAG, n); + SkPicture::WriteTagSize(buffer, SK_PICT_PAINT_BUFFER_TAG, n); for (i = 0; i < n; i++) { buffer.writePaint((*fPaints)[i]); } } - if ((n = SafeCount(fPathHeap.get())) > 0) { - write_tag_size(buffer, SK_PICT_PATH_BUFFER_TAG, n); - fPathHeap->flatten(buffer); - } + fPicture->flattenToBuffer(buffer); } void SkPicturePlayback::serialize(SkWStream* stream, SkPicture::EncodeBitmap encoder) const { - write_tag_size(stream, SK_PICT_READER_TAG, fOpData->size()); + SkPicture::WriteTagSize(stream, SK_PICT_READER_TAG, fOpData->size()); stream->write(fOpData->bytes(), fOpData->size()); if (fPictureCount > 0) { - write_tag_size(stream, SK_PICT_PICTURE_TAG, fPictureCount); + SkPicture::WriteTagSize(stream, SK_PICT_PICTURE_TAG, fPictureCount); for (int i = 0; i < fPictureCount; i++) { fPictureRefs[i]->serialize(stream, encoder); } @@ -431,10 +417,10 @@ void SkPicturePlayback::serialize(SkWStream* stream, // We have to write these two sets into the stream *before* we write // the buffer, since parsing that buffer will require that we already // have these sets available to use. - write_factories(stream, factSet); - write_typefaces(stream, typefaceSet); + WriteFactories(stream, factSet); + WriteTypefaces(stream, typefaceSet); - write_tag_size(stream, SK_PICT_BUFFER_SIZE_TAG, buffer.bytesWritten()); + SkPicture::WriteTagSize(stream, SK_PICT_BUFFER_SIZE_TAG, buffer.bytesWritten()); buffer.writeToStream(stream); } @@ -442,11 +428,11 @@ void SkPicturePlayback::serialize(SkWStream* stream, } void SkPicturePlayback::flatten(SkWriteBuffer& buffer) const { - write_tag_size(buffer, SK_PICT_READER_TAG, fOpData->size()); + SkPicture::WriteTagSize(buffer, SK_PICT_READER_TAG, fOpData->size()); buffer.writeByteArray(fOpData->bytes(), fOpData->size()); if (fPictureCount > 0) { - write_tag_size(buffer, SK_PICT_PICTURE_TAG, fPictureCount); + SkPicture::WriteTagSize(buffer, SK_PICT_PICTURE_TAG, fPictureCount); for (int i = 0; i < fPictureCount; i++) { fPictureRefs[i]->flatten(buffer); } @@ -482,7 +468,8 @@ static uint32_t pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags) { return rbMask; } -bool SkPicturePlayback::parseStreamTag(SkStream* stream, +bool SkPicturePlayback::parseStreamTag(SkPicture* picture, + SkStream* stream, uint32_t tag, uint32_t size, SkPicture::InstallPixelRefProc proc) { @@ -584,7 +571,7 @@ bool SkPicturePlayback::parseStreamTag(SkStream* stream, while (!buffer.eof()) { tag = buffer.readUInt(); size = buffer.readUInt(); - if (!this->parseBufferTag(buffer, tag, size)) { + if (!this->parseBufferTag(picture, buffer, tag, size)) { return false; } } @@ -594,7 +581,8 @@ bool SkPicturePlayback::parseStreamTag(SkStream* stream, return true; // success } -bool SkPicturePlayback::parseBufferTag(SkReadBuffer& buffer, +bool SkPicturePlayback::parseBufferTag(SkPicture* picture, + SkReadBuffer& buffer, uint32_t tag, uint32_t size) { switch (tag) { case SK_PICT_BITMAP_BUFFER_TAG: { @@ -614,9 +602,7 @@ bool SkPicturePlayback::parseBufferTag(SkReadBuffer& buffer, } } break; case SK_PICT_PATH_BUFFER_TAG: - if (size > 0) { - fPathHeap.reset(SkNEW_ARGS(SkPathHeap, (buffer))); - } + picture->parseBufferTag(buffer, tag, size); break; case SK_PICT_READER_TAG: { SkAutoMalloc storage(size); @@ -660,29 +646,32 @@ bool SkPicturePlayback::parseBufferTag(SkReadBuffer& buffer, return true; // success } -SkPicturePlayback* SkPicturePlayback::CreateFromStream(SkStream* stream, +SkPicturePlayback* SkPicturePlayback::CreateFromStream(SkPicture* picture, + SkStream* stream, const SkPictInfo& info, SkPicture::InstallPixelRefProc proc) { - SkAutoTDelete playback(SkNEW_ARGS(SkPicturePlayback, (info))); + SkAutoTDelete playback(SkNEW_ARGS(SkPicturePlayback, (picture, info))); - if (!playback->parseStream(stream, proc)) { + if (!playback->parseStream(picture, stream, proc)) { return NULL; } return playback.detach(); } -SkPicturePlayback* SkPicturePlayback::CreateFromBuffer(SkReadBuffer& buffer, +SkPicturePlayback* SkPicturePlayback::CreateFromBuffer(SkPicture* picture, + SkReadBuffer& buffer, const SkPictInfo& info) { - SkAutoTDelete playback(SkNEW_ARGS(SkPicturePlayback, (info))); + SkAutoTDelete playback(SkNEW_ARGS(SkPicturePlayback, (picture, info))); buffer.setPictureVersion(info.fVersion); - if (!playback->parseBuffer(buffer)) { + if (!playback->parseBuffer(picture, buffer)) { return NULL; } return playback.detach(); } -bool SkPicturePlayback::parseStream(SkStream* stream, +bool SkPicturePlayback::parseStream(SkPicture* picture, + SkStream* stream, SkPicture::InstallPixelRefProc proc) { for (;;) { uint32_t tag = stream->readU32(); @@ -691,14 +680,14 @@ bool SkPicturePlayback::parseStream(SkStream* stream, } uint32_t size = stream->readU32(); - if (!this->parseStreamTag(stream, tag, size, proc)) { + if (!this->parseStreamTag(picture, stream, tag, size, proc)) { return false; // we're invalid } } return true; } -bool SkPicturePlayback::parseBuffer(SkReadBuffer& buffer) { +bool SkPicturePlayback::parseBuffer(SkPicture* picture, SkReadBuffer& buffer) { for (;;) { uint32_t tag = buffer.readUInt(); if (SK_PICT_EOF_TAG == tag) { @@ -706,7 +695,7 @@ bool SkPicturePlayback::parseBuffer(SkReadBuffer& buffer) { } uint32_t size = buffer.readUInt(); - if (!this->parseBufferTag(buffer, tag, size)) { + if (!this->parseBufferTag(picture, buffer, tag, size)) { return false; // we're invalid } } diff --git a/src/core/SkPicturePlayback.h b/src/core/SkPicturePlayback.h index cae8841..8df4278 100644 --- a/src/core/SkPicturePlayback.h +++ b/src/core/SkPicturePlayback.h @@ -75,12 +75,17 @@ struct SkPictCopyInfo { class SkPicturePlayback { public: - SkPicturePlayback(const SkPicturePlayback& src, SkPictCopyInfo* deepCopyInfo = NULL); - SkPicturePlayback(const SkPictureRecord& record, const SkPictInfo&, bool deepCopy = false); - static SkPicturePlayback* CreateFromStream(SkStream*, + SkPicturePlayback(const SkPicture* picture, const SkPicturePlayback& src, + SkPictCopyInfo* deepCopyInfo = NULL); + SkPicturePlayback(const SkPicture* picture, const SkPictureRecord& record, const SkPictInfo&, + bool deepCopy = false); + static SkPicturePlayback* CreateFromStream(SkPicture* picture, + SkStream*, const SkPictInfo&, SkPicture::InstallPixelRefProc); - static SkPicturePlayback* CreateFromBuffer(SkReadBuffer&, const SkPictInfo&); + static SkPicturePlayback* CreateFromBuffer(SkPicture* picture, + SkReadBuffer&, + const SkPictInfo&); virtual ~SkPicturePlayback(); @@ -105,10 +110,10 @@ public: void resetOpID() { fCurOffset = 0; } protected: - explicit SkPicturePlayback(const SkPictInfo& info); + explicit SkPicturePlayback(const SkPicture* picture, const SkPictInfo& info); - bool parseStream(SkStream*, SkPicture::InstallPixelRefProc); - bool parseBuffer(SkReadBuffer& buffer); + bool parseStream(SkPicture* picture, SkStream*, SkPicture::InstallPixelRefProc); + bool parseBuffer(SkPicture* picture, SkReadBuffer& buffer); #ifdef SK_DEVELOPER virtual bool preDraw(int opIndex, int type); virtual void postDraw(int opIndex); @@ -139,7 +144,7 @@ private: } const SkPath& getPath(SkReader32& reader) { - return (*fPathHeap)[reader.readInt() - 1]; + return fPicture->getPath(reader.readInt() - 1); } SkPicture& getPicture(SkReader32& reader) { @@ -215,17 +220,20 @@ public: #endif private: // these help us with reading/writing - bool parseStreamTag(SkStream*, uint32_t tag, uint32_t size, SkPicture::InstallPixelRefProc); - bool parseBufferTag(SkReadBuffer&, uint32_t tag, uint32_t size); + bool parseStreamTag(SkPicture* picture, SkStream*, uint32_t tag, uint32_t size, + SkPicture::InstallPixelRefProc); + bool parseBufferTag(SkPicture* picture, SkReadBuffer&, uint32_t tag, uint32_t size); void flattenToBuffer(SkWriteBuffer&) const; private: + // The picture that owns this SkPicturePlayback object + const SkPicture* fPicture; + // Only used by getBitmap() if the passed in index is SkBitmapHeap::INVALID_SLOT. This empty // bitmap allows playback to draw nothing and move on. SkBitmap fBadBitmap; SkAutoTUnref fBitmapHeap; - SkAutoTUnref fPathHeap; SkTRefArray* fBitmaps; SkTRefArray* fPaints; @@ -269,6 +277,9 @@ private: const SkPictInfo fInfo; + static void WriteFactories(SkWStream* stream, const SkFactorySet& rec); + static void WriteTypefaces(SkWStream* stream, const SkRefCntSet& rec); + #ifdef SK_BUILD_FOR_ANDROID SkMutex fDrawMutex; bool fAbortCurrentPlayback; diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp index c5e329e..f4fc736 100644 --- a/src/core/SkPictureRecord.cpp +++ b/src/core/SkPictureRecord.cpp @@ -27,7 +27,7 @@ static const uint32_t kSaveSize = 2 * kUInt32Size; static const uint32_t kSaveLayerNoBoundsSize = 4 * kUInt32Size; static const uint32_t kSaveLayerWithBoundsSize = 4 * kUInt32Size + sizeof(SkRect); -SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags) +SkPictureRecord::SkPictureRecord(SkPicture* picture, const SkISize& dimensions, uint32_t flags) : INHERITED(dimensions.width(), dimensions.height()) , fBoundingHierarchy(NULL) , fStateTree(NULL) @@ -40,9 +40,9 @@ SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags) fPointWrites = fRectWrites = fTextWrites = 0; #endif + fPicture = picture; fBitmapHeap = SkNEW(SkBitmapHeap); fFlattenableHeap.setBitmapStorage(fBitmapHeap); - fPathHeap = NULL; // lazy allocate #ifndef SK_COLLAPSE_MATRIX_CLIP_STATE fFirstSavedLayerIndex = kNoSavedLayerIndex; @@ -57,7 +57,6 @@ SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags) SkPictureRecord::~SkPictureRecord() { SkSafeUnref(fBitmapHeap); - SkSafeUnref(fPathHeap); SkSafeUnref(fBoundingHierarchy); SkSafeUnref(fStateTree); fFlattenableHeap.setBitmapStorage(NULL); @@ -1590,14 +1589,7 @@ void SkPictureRecord::addFlatPaint(const SkFlatData* flatPaint) { } int SkPictureRecord::addPathToHeap(const SkPath& path) { - if (NULL == fPathHeap) { - fPathHeap = SkNEW(SkPathHeap); - } -#ifdef SK_DEDUP_PICTURE_PATHS - return fPathHeap->insert(path); -#else - return fPathHeap->append(path); -#endif + return fPicture->addPathToHeap(path); } void SkPictureRecord::addPath(const SkPath& path) { diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h index 257bab2..0f0986f 100644 --- a/src/core/SkPictureRecord.h +++ b/src/core/SkPictureRecord.h @@ -33,7 +33,7 @@ class SkPictureStateTree; class SkPictureRecord : public SkCanvas { public: - SkPictureRecord(const SkISize& dimensions, uint32_t recordFlags); + SkPictureRecord(SkPicture* picture, const SkISize& dimensions, uint32_t recordFlags); virtual ~SkPictureRecord(); virtual void clear(SkColor) SK_OVERRIDE; @@ -279,6 +279,9 @@ protected: SkBitmapHeap* fBitmapHeap; private: + // The owning SkPicture + SkPicture* fPicture; + friend class MatrixClipState; // for access to *Impl methods friend class SkMatrixClipStateMgr; // for access to *Impl methods @@ -286,7 +289,6 @@ private: SkPaintDictionary fPaints; - SkPathHeap* fPathHeap; // reference counted SkWriter32 fWriter; // we ref each item in these arrays diff --git a/tests/CanvasTest.cpp b/tests/CanvasTest.cpp index 3b259ab..a1c28dd 100644 --- a/tests/CanvasTest.cpp +++ b/tests/CanvasTest.cpp @@ -695,8 +695,8 @@ private: testStep->assertMessage()); } REPORTER_ASSERT_MESSAGE(reporter, - !referenceRecord->fPathHeap == - !testRecord->fPathHeap, + !referenceRecord->fPicture->fPathHeap == + !testRecord->fPicture->fPathHeap, testStep->assertMessage()); // The following tests are commented out because they currently // fail. Issue: http://code.google.com/p/skia/issues/detail?id=507 -- 2.7.4