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
This commit is contained in:
commit-bot@chromium.org 2014-04-23 22:35:42 +00:00
parent dcbc360567
commit 8f831f262f
11 changed files with 217 additions and 118 deletions

View File

@ -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<bool>& deletedCommands) {
// Mimics SkPicturePlayback::CreateFromStream
SkAutoTDelete<SkTimedPicturePlayback> 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<bool>& deletedCommands, const SkPictInfo& info)
: INHERITED(info)
SkTimedPicturePlayback(SkPicture* picture,
const SkTDArray<bool>& 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(); }

View File

@ -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<SkPathHeap> 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 {

View File

@ -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();

View File

@ -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;

View File

@ -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() { }
/**

View File

@ -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,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, &copyInfo));
clone->fPlayback = SkNEW_ARGS(SkPicturePlayback, (clone, *fPlayback, &copyInfo));
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<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 @@ 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));

View File

@ -23,14 +23,18 @@ template <typename T> 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<SkPicture* >& 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<SkPicturePlayback> playback(SkNEW_ARGS(SkPicturePlayback, (info)));
SkAutoTDelete<SkPicturePlayback> 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<SkPicturePlayback> playback(SkNEW_ARGS(SkPicturePlayback, (info)));
SkAutoTDelete<SkPicturePlayback> 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
}
}

View File

@ -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<SkBitmapHeap> fBitmapHeap;
SkAutoTUnref<SkPathHeap> fPathHeap;
SkTRefArray<SkBitmap>* fBitmaps;
SkTRefArray<SkPaint>* 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;

View File

@ -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) {

View File

@ -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

View File

@ -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