| Index: src/core/SkPicture.cpp
|
| ===================================================================
|
| --- src/core/SkPicture.cpp (revision 14323)
|
| +++ src/core/SkPicture.cpp (working copy)
|
| @@ -31,6 +31,10 @@
|
| #include "GrContext.h"
|
| #endif
|
|
|
| +template <typename T> 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,19 +143,50 @@
|
| 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() {
|
| SkSafeUnref(fRecord);
|
| SkDELETE(fPlayback);
|
| @@ -171,6 +206,7 @@
|
| SkTSwap(fAccelData, other.fAccelData);
|
| SkTSwap(fWidth, other.fWidth);
|
| SkTSwap(fHeight, other.fHeight);
|
| + fPathHeap.swap(&other.fPathHeap);
|
| }
|
|
|
| SkPicture* SkPicture::clone() const {
|
| @@ -198,15 +234,17 @@
|
| 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 @@
|
| }
|
| SkSafeUnref(fAccelData);
|
| SkSafeSetNull(fRecord);
|
| + SkASSERT(NULL == fPathHeap);
|
|
|
| this->needsNewGenID();
|
|
|
| @@ -277,12 +316,12 @@
|
| if (NULL != bbhFactory) {
|
| SkAutoTUnref<SkBBoxHierarchy> 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 @@
|
| 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 @@
|
| 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 @@
|
| 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 @@
|
| 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::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));
|
|
|