SkPicturePlayback.h revision 3d41c4add81e95784faa81f9a59b4a32b7cff082
1 2/* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9#ifndef SkPicturePlayback_DEFINED 10#define SkPicturePlayback_DEFINED 11 12#include "SkPicture.h" 13#include "SkReader32.h" 14 15#include "SkBitmap.h" 16#include "SkData.h" 17#include "SkMatrix.h" 18#include "SkReadBuffer.h" 19#include "SkPaint.h" 20#include "SkPath.h" 21#include "SkPathHeap.h" 22#include "SkRegion.h" 23#include "SkRRect.h" 24#include "SkPictureFlat.h" 25 26#ifdef SK_BUILD_FOR_ANDROID 27#include "SkThread.h" 28#endif 29 30class SkPictureRecord; 31class SkStream; 32class SkWStream; 33class SkBBoxHierarchy; 34class SkPictureStateTree; 35 36struct SkPictInfo { 37 enum Flags { 38 kCrossProcess_Flag = 1 << 0, 39 kScalarIsFloat_Flag = 1 << 1, 40 kPtrIs64Bit_Flag = 1 << 2, 41 }; 42 43 char fMagic[8]; 44 uint32_t fVersion; 45 uint32_t fWidth; 46 uint32_t fHeight; 47 uint32_t fFlags; 48}; 49 50#define SK_PICT_READER_TAG SkSetFourByteTag('r', 'e', 'a', 'd') 51#define SK_PICT_FACTORY_TAG SkSetFourByteTag('f', 'a', 'c', 't') 52#define SK_PICT_TYPEFACE_TAG SkSetFourByteTag('t', 'p', 'f', 'c') 53#define SK_PICT_PICTURE_TAG SkSetFourByteTag('p', 'c', 't', 'r') 54 55// This tag specifies the size of the ReadBuffer, needed for the following tags 56#define SK_PICT_BUFFER_SIZE_TAG SkSetFourByteTag('a', 'r', 'a', 'y') 57// these are all inside the ARRAYS tag 58#define SK_PICT_BITMAP_BUFFER_TAG SkSetFourByteTag('b', 't', 'm', 'p') 59#define SK_PICT_PAINT_BUFFER_TAG SkSetFourByteTag('p', 'n', 't', ' ') 60#define SK_PICT_PATH_BUFFER_TAG SkSetFourByteTag('p', 't', 'h', ' ') 61 62// Always write this guy last (with no length field afterwards) 63#define SK_PICT_EOF_TAG SkSetFourByteTag('e', 'o', 'f', ' ') 64 65/** 66 * Container for data that is needed to deep copy a SkPicture. The container 67 * enables the data to be generated once and reused for subsequent copies. 68 */ 69struct SkPictCopyInfo { 70 SkPictCopyInfo() : initialized(false), controller(1024) {} 71 72 bool initialized; 73 SkChunkFlatController controller; 74 SkTDArray<SkFlatData*> paintData; 75}; 76 77class SkPicturePlayback { 78public: 79 SkPicturePlayback(const SkPicture* picture, const SkPicturePlayback& src, 80 SkPictCopyInfo* deepCopyInfo = NULL); 81 SkPicturePlayback(const SkPicture* picture, const SkPictureRecord& record, const SkPictInfo&, 82 bool deepCopy = false); 83 static SkPicturePlayback* CreateFromStream(SkPicture* picture, 84 SkStream*, 85 const SkPictInfo&, 86 SkPicture::InstallPixelRefProc); 87 static SkPicturePlayback* CreateFromBuffer(SkPicture* picture, 88 SkReadBuffer&, 89 const SkPictInfo&); 90 91 virtual ~SkPicturePlayback(); 92 93 const SkPicture::OperationList& getActiveOps(const SkIRect& queryRect); 94 95 void setUseBBH(bool useBBH) { fUseBBH = useBBH; } 96 97 void draw(SkCanvas& canvas, SkDrawPictureCallback*); 98 99 void serialize(SkWStream*, SkPicture::EncodeBitmap) const; 100 void flatten(SkWriteBuffer&) const; 101 102 void dumpSize() const; 103 104 bool containsBitmaps() const; 105 106#ifdef SK_BUILD_FOR_ANDROID 107 // Can be called in the middle of playback (the draw() call). WIll abort the 108 // drawing and return from draw() after the "current" op code is done 109 void abort() { fAbortCurrentPlayback = true; } 110#endif 111 112 size_t curOpID() const { return fCurOffset; } 113 void resetOpID() { fCurOffset = 0; } 114 115protected: 116 explicit SkPicturePlayback(const SkPicture* picture, const SkPictInfo& info); 117 118 bool parseStream(SkPicture* picture, SkStream*, SkPicture::InstallPixelRefProc); 119 bool parseBuffer(SkPicture* picture, SkReadBuffer& buffer); 120#ifdef SK_DEVELOPER 121 virtual bool preDraw(int opIndex, int type); 122 virtual void postDraw(int opIndex); 123#endif 124 125private: 126 class TextContainer { 127 public: 128 size_t length() { return fByteLength; } 129 const void* text() { return (const void*) fText; } 130 size_t fByteLength; 131 const char* fText; 132 }; 133 134 const SkBitmap& getBitmap(SkReader32& reader) { 135 const int index = reader.readInt(); 136 if (SkBitmapHeap::INVALID_SLOT == index) { 137#ifdef SK_DEBUG 138 SkDebugf("An invalid bitmap was recorded!\n"); 139#endif 140 return fBadBitmap; 141 } 142 return (*fBitmaps)[index]; 143 } 144 145 void getMatrix(SkReader32& reader, SkMatrix* matrix) { 146 reader.readMatrix(matrix); 147 } 148 149 const SkPath& getPath(SkReader32& reader) { 150 return fPicture->getPath(reader.readInt() - 1); 151 } 152 153 SkPicture& getPicture(SkReader32& reader) { 154 int index = reader.readInt(); 155 SkASSERT(index > 0 && index <= fPictureCount); 156 return *fPictureRefs[index - 1]; 157 } 158 159 const SkPaint* getPaint(SkReader32& reader) { 160 int index = reader.readInt(); 161 if (index == 0) { 162 return NULL; 163 } 164 return &(*fPaints)[index - 1]; 165 } 166 167 const SkRect* getRectPtr(SkReader32& reader) { 168 if (reader.readBool()) { 169 return &reader.skipT<SkRect>(); 170 } else { 171 return NULL; 172 } 173 } 174 175 const SkIRect* getIRectPtr(SkReader32& reader) { 176 if (reader.readBool()) { 177 return &reader.skipT<SkIRect>(); 178 } else { 179 return NULL; 180 } 181 } 182 183 void getRegion(SkReader32& reader, SkRegion* region) { 184 reader.readRegion(region); 185 } 186 187 void getText(SkReader32& reader, TextContainer* text) { 188 size_t length = text->fByteLength = reader.readInt(); 189 text->fText = (const char*)reader.skip(length); 190 } 191 192 void init(); 193 194#ifdef SK_DEBUG_SIZE 195public: 196 int size(size_t* sizePtr); 197 int bitmaps(size_t* size); 198 int paints(size_t* size); 199 int paths(size_t* size); 200#endif 201 202#ifdef SK_DEBUG_DUMP 203private: 204 void dumpBitmap(const SkBitmap& bitmap) const; 205 void dumpMatrix(const SkMatrix& matrix) const; 206 void dumpPaint(const SkPaint& paint) const; 207 void dumpPath(const SkPath& path) const; 208 void dumpPicture(const SkPicture& picture) const; 209 void dumpRegion(const SkRegion& region) const; 210 int dumpDrawType(char* bufferPtr, char* buffer, DrawType drawType); 211 int dumpInt(char* bufferPtr, char* buffer, char* name); 212 int dumpRect(char* bufferPtr, char* buffer, char* name); 213 int dumpPoint(char* bufferPtr, char* buffer, char* name); 214 void dumpPointArray(char** bufferPtrPtr, char* buffer, int count); 215 int dumpPtr(char* bufferPtr, char* buffer, char* name, void* ptr); 216 int dumpRectPtr(char* bufferPtr, char* buffer, char* name); 217 int dumpScalar(char* bufferPtr, char* buffer, char* name); 218 void dumpText(char** bufferPtrPtr, char* buffer); 219 void dumpStream(); 220 221public: 222 void dump() const; 223#endif 224 225private: // these help us with reading/writing 226 bool parseStreamTag(SkPicture* picture, SkStream*, uint32_t tag, uint32_t size, 227 SkPicture::InstallPixelRefProc); 228 bool parseBufferTag(SkPicture* picture, SkReadBuffer&, uint32_t tag, uint32_t size); 229 void flattenToBuffer(SkWriteBuffer&) const; 230 231private: 232 friend class SkPicture; 233 friend class SkGpuDevice; // for access to setDrawLimits & setReplacements 234 235 // The picture that owns this SkPicturePlayback object 236 const SkPicture* fPicture; 237 238 // Only used by getBitmap() if the passed in index is SkBitmapHeap::INVALID_SLOT. This empty 239 // bitmap allows playback to draw nothing and move on. 240 SkBitmap fBadBitmap; 241 242 SkAutoTUnref<SkBitmapHeap> fBitmapHeap; 243 244 SkTRefArray<SkBitmap>* fBitmaps; 245 SkTRefArray<SkPaint>* fPaints; 246 247 SkData* fOpData; // opcodes and parameters 248 249 SkPicture** fPictureRefs; 250 int fPictureCount; 251 252 SkBBoxHierarchy* fBoundingHierarchy; 253 SkPictureStateTree* fStateTree; 254 255 // Limit the opcode playback to be between the offsets 'start' and 'stop'. 256 // The opcode at 'start' should be a saveLayer while the opcode at 257 // 'stop' should be a restore. Neither of those commands will be issued. 258 // Set both start & stop to 0 to disable draw limiting 259 // Draw limiting cannot be enabled at the same time as draw replacing 260 void setDrawLimits(size_t start, size_t stop) { 261 SkASSERT(NULL == fReplacements); 262 fStart = start; 263 fStop = stop; 264 } 265 266 // PlaybackReplacements collects op ranges that can be replaced with 267 // a single drawBitmap call (using a precomputed bitmap). 268 class PlaybackReplacements { 269 public: 270 // All the operations between fStart and fStop (inclusive) will be replaced with 271 // a single drawBitmap call using fPos, fBM and fPaint. 272 // fPaint will be NULL if the picture's paint wasn't copyable 273 struct ReplacementInfo { 274 size_t fStart; 275 size_t fStop; 276 SkPoint fPos; 277 SkBitmap* fBM; 278 const SkPaint* fPaint; // Note: this object doesn't own the paint 279 }; 280 281 ~PlaybackReplacements() { this->freeAll(); } 282 283 // Add a new replacement range. The replacement ranges should be 284 // sorted in increasing order and non-overlapping (esp. no nested 285 // saveLayers). 286 ReplacementInfo* push(); 287 288 private: 289 friend class SkPicturePlayback; // for access to lookupByStart 290 291 // look up a replacement range by its start offset 292 ReplacementInfo* lookupByStart(size_t start); 293 294 void freeAll(); 295 296 #ifdef SK_DEBUG 297 void validate() const; 298 #endif 299 300 SkTDArray<ReplacementInfo> fReplacements; 301 }; 302 303 304 // Replace all the draw ops in the replacement ranges in 'replacements' with 305 // the associated drawBitmap call 306 // Draw replacing cannot be enabled at the same time as draw limiting 307 void setReplacements(PlaybackReplacements* replacements) { 308 SkASSERT(fStart == 0 && fStop == 0); 309 fReplacements = replacements; 310 } 311 312 bool fUseBBH; 313 size_t fStart; 314 size_t fStop; 315 PlaybackReplacements* fReplacements; 316 317 class CachedOperationList : public SkPicture::OperationList { 318 public: 319 CachedOperationList() { 320 fCacheQueryRect.setEmpty(); 321 } 322 323 virtual bool valid() const { return true; } 324 virtual int numOps() const SK_OVERRIDE { return fOps.count(); } 325 virtual uint32_t offset(int index) const SK_OVERRIDE; 326 virtual const SkMatrix& matrix(int index) const SK_OVERRIDE; 327 328 // The query rect for which the cached active ops are valid 329 SkIRect fCacheQueryRect; 330 331 // The operations which are active within 'fCachedQueryRect' 332 SkTDArray<void*> fOps; 333 334 private: 335 typedef SkPicture::OperationList INHERITED; 336 }; 337 338 CachedOperationList* fCachedActiveOps; 339 340 SkTypefacePlayback fTFPlayback; 341 SkFactoryPlayback* fFactoryPlayback; 342 343 // The offset of the current operation when within the draw method 344 size_t fCurOffset; 345 346 const SkPictInfo fInfo; 347 348 static void WriteFactories(SkWStream* stream, const SkFactorySet& rec); 349 static void WriteTypefaces(SkWStream* stream, const SkRefCntSet& rec); 350 351#ifdef SK_BUILD_FOR_ANDROID 352 SkMutex fDrawMutex; 353 bool fAbortCurrentPlayback; 354#endif 355}; 356 357#endif 358