/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#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 "SkPathHeap.h"
#include "SkRegion.h"
#include "SkPictureFlat.h"
#ifdef SK_BUILD_FOR_ANDROID
#include "SkThread.h"
#endif
class SkPictureRecord;
class SkStream;
class SkWStream;
class SkPicturePlayback {
public:
SkPicturePlayback();
SkPicturePlayback(const SkPicturePlayback& src);
explicit SkPicturePlayback(const SkPictureRecord& record);
explicit SkPicturePlayback(SkStream*, uint32_t pictureVersion = PICTURE_VERSION_JB);
virtual ~SkPicturePlayback();
void draw(SkCanvas& canvas);
void serialize(SkWStream*) const;
void dumpSize() const;
// Can be called in the middle of playback (the draw() call). WIll abort the
// drawing and return from draw() after the "current" op code is done
void abort();
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() {
return (*fPathHeap)[getInt() - 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.skipT<SkRect>();
} else {
return NULL;
}
}
const SkIRect* getIRectPtr() {
if (fReader.readBool()) {
return &fReader.skipT<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:
SkPathHeap* fPathHeap; // reference counted
SkBitmap* fBitmaps;
int fBitmapCount;
SkMatrix* fMatrices;
int fMatrixCount;
SkPaint* fPaints;
int fPaintCount;
SkRegion* fRegions;
int fRegionCount;
mutable SkFlattenableReadBuffer fReader;
SkPicture** fPictureRefs;
int fPictureCount;
SkRefCntPlayback fRCPlayback;
SkTypefacePlayback fTFPlayback;
SkFactoryPlayback* fFactoryPlayback;
#ifdef SK_BUILD_FOR_ANDROID
SkMutex fDrawMutex;
#endif
};
#endif