michael@0: michael@0: /* michael@0: * Copyright 2011 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: #ifndef SkPicturePlayback_DEFINED michael@0: #define SkPicturePlayback_DEFINED michael@0: michael@0: #include "SkPicture.h" michael@0: #include "SkReader32.h" michael@0: michael@0: #include "SkBitmap.h" michael@0: #include "SkData.h" michael@0: #include "SkMatrix.h" michael@0: #include "SkReadBuffer.h" michael@0: #include "SkPaint.h" michael@0: #include "SkPath.h" michael@0: #include "SkPathHeap.h" michael@0: #include "SkRegion.h" michael@0: #include "SkRRect.h" michael@0: #include "SkPictureFlat.h" michael@0: michael@0: #ifdef SK_BUILD_FOR_ANDROID michael@0: #include "SkThread.h" michael@0: #endif michael@0: michael@0: class SkPictureRecord; michael@0: class SkStream; michael@0: class SkWStream; michael@0: class SkBBoxHierarchy; michael@0: class SkPictureStateTree; michael@0: class SkOffsetTable; michael@0: michael@0: struct SkPictInfo { michael@0: enum Flags { michael@0: kCrossProcess_Flag = 1 << 0, michael@0: kScalarIsFloat_Flag = 1 << 1, michael@0: kPtrIs64Bit_Flag = 1 << 2, michael@0: }; michael@0: michael@0: char fMagic[8]; michael@0: uint32_t fVersion; michael@0: uint32_t fWidth; michael@0: uint32_t fHeight; michael@0: uint32_t fFlags; michael@0: }; michael@0: michael@0: #define SK_PICT_READER_TAG SkSetFourByteTag('r', 'e', 'a', 'd') michael@0: #define SK_PICT_FACTORY_TAG SkSetFourByteTag('f', 'a', 'c', 't') michael@0: #define SK_PICT_TYPEFACE_TAG SkSetFourByteTag('t', 'p', 'f', 'c') michael@0: #define SK_PICT_PICTURE_TAG SkSetFourByteTag('p', 'c', 't', 'r') michael@0: michael@0: // This tag specifies the size of the ReadBuffer, needed for the following tags michael@0: #define SK_PICT_BUFFER_SIZE_TAG SkSetFourByteTag('a', 'r', 'a', 'y') michael@0: // these are all inside the ARRAYS tag michael@0: #define SK_PICT_BITMAP_BUFFER_TAG SkSetFourByteTag('b', 't', 'm', 'p') michael@0: #define SK_PICT_PAINT_BUFFER_TAG SkSetFourByteTag('p', 'n', 't', ' ') michael@0: #define SK_PICT_PATH_BUFFER_TAG SkSetFourByteTag('p', 't', 'h', ' ') michael@0: michael@0: // Always write this guy last (with no length field afterwards) michael@0: #define SK_PICT_EOF_TAG SkSetFourByteTag('e', 'o', 'f', ' ') michael@0: michael@0: /** michael@0: * Container for data that is needed to deep copy a SkPicture. The container michael@0: * enables the data to be generated once and reused for subsequent copies. michael@0: */ michael@0: struct SkPictCopyInfo { michael@0: SkPictCopyInfo() : initialized(false), controller(1024) {} michael@0: michael@0: bool initialized; michael@0: SkChunkFlatController controller; michael@0: SkTDArray paintData; michael@0: }; michael@0: michael@0: class SkPicturePlayback { michael@0: public: michael@0: SkPicturePlayback(); michael@0: SkPicturePlayback(const SkPicturePlayback& src, SkPictCopyInfo* deepCopyInfo = NULL); michael@0: explicit SkPicturePlayback(const SkPictureRecord& record, bool deepCopy = false); michael@0: static SkPicturePlayback* CreateFromStream(SkStream*, const SkPictInfo&, michael@0: SkPicture::InstallPixelRefProc); michael@0: static SkPicturePlayback* CreateFromBuffer(SkReadBuffer&); michael@0: michael@0: virtual ~SkPicturePlayback(); michael@0: michael@0: void draw(SkCanvas& canvas, SkDrawPictureCallback*); michael@0: michael@0: void serialize(SkWStream*, SkPicture::EncodeBitmap) const; michael@0: void flatten(SkWriteBuffer&) const; michael@0: michael@0: void dumpSize() const; michael@0: michael@0: bool containsBitmaps() const; michael@0: michael@0: #ifdef SK_BUILD_FOR_ANDROID michael@0: // Can be called in the middle of playback (the draw() call). WIll abort the michael@0: // drawing and return from draw() after the "current" op code is done michael@0: void abort() { fAbortCurrentPlayback = true; } michael@0: #endif michael@0: michael@0: protected: michael@0: bool parseStream(SkStream*, const SkPictInfo&, michael@0: SkPicture::InstallPixelRefProc); michael@0: bool parseBuffer(SkReadBuffer& buffer); michael@0: #ifdef SK_DEVELOPER michael@0: virtual bool preDraw(int opIndex, int type); michael@0: virtual void postDraw(int opIndex); michael@0: #endif michael@0: michael@0: void preLoadBitmaps(const SkTDArray& results); michael@0: michael@0: private: michael@0: class TextContainer { michael@0: public: michael@0: size_t length() { return fByteLength; } michael@0: const void* text() { return (const void*) fText; } michael@0: size_t fByteLength; michael@0: const char* fText; michael@0: }; michael@0: michael@0: const SkBitmap& getBitmap(SkReader32& reader) { michael@0: const int index = reader.readInt(); michael@0: if (SkBitmapHeap::INVALID_SLOT == index) { michael@0: #ifdef SK_DEBUG michael@0: SkDebugf("An invalid bitmap was recorded!\n"); michael@0: #endif michael@0: return fBadBitmap; michael@0: } michael@0: return (*fBitmaps)[index]; michael@0: } michael@0: michael@0: void getMatrix(SkReader32& reader, SkMatrix* matrix) { michael@0: reader.readMatrix(matrix); michael@0: } michael@0: michael@0: const SkPath& getPath(SkReader32& reader) { michael@0: return (*fPathHeap)[reader.readInt() - 1]; michael@0: } michael@0: michael@0: SkPicture& getPicture(SkReader32& reader) { michael@0: int index = reader.readInt(); michael@0: SkASSERT(index > 0 && index <= fPictureCount); michael@0: return *fPictureRefs[index - 1]; michael@0: } michael@0: michael@0: const SkPaint* getPaint(SkReader32& reader) { michael@0: int index = reader.readInt(); michael@0: if (index == 0) { michael@0: return NULL; michael@0: } michael@0: return &(*fPaints)[index - 1]; michael@0: } michael@0: michael@0: const SkRect* getRectPtr(SkReader32& reader) { michael@0: if (reader.readBool()) { michael@0: return &reader.skipT(); michael@0: } else { michael@0: return NULL; michael@0: } michael@0: } michael@0: michael@0: const SkIRect* getIRectPtr(SkReader32& reader) { michael@0: if (reader.readBool()) { michael@0: return &reader.skipT(); michael@0: } else { michael@0: return NULL; michael@0: } michael@0: } michael@0: michael@0: void getRegion(SkReader32& reader, SkRegion* region) { michael@0: reader.readRegion(region); michael@0: } michael@0: michael@0: void getText(SkReader32& reader, TextContainer* text) { michael@0: size_t length = text->fByteLength = reader.readInt(); michael@0: text->fText = (const char*)reader.skip(length); michael@0: } michael@0: michael@0: void init(); michael@0: michael@0: #ifdef SK_DEBUG_SIZE michael@0: public: michael@0: int size(size_t* sizePtr); michael@0: int bitmaps(size_t* size); michael@0: int paints(size_t* size); michael@0: int paths(size_t* size); michael@0: #endif michael@0: michael@0: #ifdef SK_DEBUG_DUMP michael@0: private: michael@0: void dumpBitmap(const SkBitmap& bitmap) const; michael@0: void dumpMatrix(const SkMatrix& matrix) const; michael@0: void dumpPaint(const SkPaint& paint) const; michael@0: void dumpPath(const SkPath& path) const; michael@0: void dumpPicture(const SkPicture& picture) const; michael@0: void dumpRegion(const SkRegion& region) const; michael@0: int dumpDrawType(char* bufferPtr, char* buffer, DrawType drawType); michael@0: int dumpInt(char* bufferPtr, char* buffer, char* name); michael@0: int dumpRect(char* bufferPtr, char* buffer, char* name); michael@0: int dumpPoint(char* bufferPtr, char* buffer, char* name); michael@0: void dumpPointArray(char** bufferPtrPtr, char* buffer, int count); michael@0: int dumpPtr(char* bufferPtr, char* buffer, char* name, void* ptr); michael@0: int dumpRectPtr(char* bufferPtr, char* buffer, char* name); michael@0: int dumpScalar(char* bufferPtr, char* buffer, char* name); michael@0: void dumpText(char** bufferPtrPtr, char* buffer); michael@0: void dumpStream(); michael@0: michael@0: public: michael@0: void dump() const; michael@0: #endif michael@0: michael@0: private: // these help us with reading/writing michael@0: bool parseStreamTag(SkStream*, const SkPictInfo&, uint32_t tag, size_t size, michael@0: SkPicture::InstallPixelRefProc); michael@0: bool parseBufferTag(SkReadBuffer&, uint32_t tag, size_t size); michael@0: void flattenToBuffer(SkWriteBuffer&) const; michael@0: michael@0: private: michael@0: // Only used by getBitmap() if the passed in index is SkBitmapHeap::INVALID_SLOT. This empty michael@0: // bitmap allows playback to draw nothing and move on. michael@0: SkBitmap fBadBitmap; michael@0: michael@0: SkAutoTUnref fBitmapHeap; michael@0: SkAutoTUnref fPathHeap; michael@0: michael@0: SkTRefArray* fBitmaps; michael@0: SkTRefArray* fPaints; michael@0: michael@0: SkData* fOpData; // opcodes and parameters michael@0: SkAutoTUnref fBitmapUseOffsets; michael@0: michael@0: SkPicture** fPictureRefs; michael@0: int fPictureCount; michael@0: michael@0: SkBBoxHierarchy* fBoundingHierarchy; michael@0: SkPictureStateTree* fStateTree; michael@0: michael@0: SkTypefacePlayback fTFPlayback; michael@0: SkFactoryPlayback* fFactoryPlayback; michael@0: #ifdef SK_BUILD_FOR_ANDROID michael@0: SkMutex fDrawMutex; michael@0: bool fAbortCurrentPlayback; michael@0: #endif michael@0: }; michael@0: michael@0: #endif