[go: nahoru, domu]

blob: b3dd6a4f0719286486a94b4d8e173dd07717206f [file] [log] [blame]
epoger@google.com685cfc02011-07-28 14:26:00 +00001
reed@android.combcd4d5a2008-12-17 15:59:43 +00002/*
epoger@google.com685cfc02011-07-28 14:26:00 +00003 * Copyright 2007 The Android Open Source Project
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
scroggo@google.com8b854502013-05-07 14:45:40 +00009
reed@android.combcd4d5a2008-12-17 15:59:43 +000010#include "SkPictureFlat.h"
11#include "SkPicturePlayback.h"
12#include "SkPictureRecord.h"
13
robertphillips@google.com2fd23902013-08-29 11:54:56 +000014#include "SkBitmapDevice.h"
reed@android.combcd4d5a2008-12-17 15:59:43 +000015#include "SkCanvas.h"
16#include "SkChunkAlloc.h"
17#include "SkPicture.h"
18#include "SkRegion.h"
19#include "SkStream.h"
20#include "SkTDArray.h"
21#include "SkTSearch.h"
22#include "SkTime.h"
23
24#include "SkReader32.h"
25#include "SkWriter32.h"
rileya@google.com7fb3d2f2012-09-13 21:41:51 +000026#include "SkRTree.h"
27#include "SkBBoxHierarchyRecord.h"
reed@android.combcd4d5a2008-12-17 15:59:43 +000028
29#define DUMP_BUFFER_SIZE 65536
30
31//#define ENABLE_TIME_DRAW // dumps milliseconds for each draw
32
33
34#ifdef SK_DEBUG
reed@google.com91911482011-02-07 15:30:46 +000035// enable SK_DEBUG_TRACE to trace DrawType elements when
reed@android.combcd4d5a2008-12-17 15:59:43 +000036// recorded and played back
37// #define SK_DEBUG_TRACE
38// enable SK_DEBUG_SIZE to see the size of picture components
39// #define SK_DEBUG_SIZE
40// enable SK_DEBUG_DUMP to see the contents of recorded elements
41// #define SK_DEBUG_DUMP
42// enable SK_DEBUG_VALIDATE to check internal structures for consistency
43// #define SK_DEBUG_VALIDATE
44#endif
45
46#if defined SK_DEBUG_TRACE || defined SK_DEBUG_DUMP
47const char* DrawTypeToString(DrawType drawType) {
48 switch (drawType) {
49 case UNUSED: SkDebugf("DrawType UNUSED\n"); SkASSERT(0); break;
50 case CLIP_PATH: return "CLIP_PATH";
51 case CLIP_REGION: return "CLIP_REGION";
52 case CLIP_RECT: return "CLIP_RECT";
robertphillips@google.come7189be2013-02-15 17:19:15 +000053 case CLIP_RRECT: return "CLIP_RRECT";
reed@android.combcd4d5a2008-12-17 15:59:43 +000054 case CONCAT: return "CONCAT";
55 case DRAW_BITMAP: return "DRAW_BITMAP";
56 case DRAW_BITMAP_MATRIX: return "DRAW_BITMAP_MATRIX";
robertphillips@google.come7189be2013-02-15 17:19:15 +000057 case DRAW_BITMAP_NINE: return "DRAW_BITMAP_NINE";
58 case DRAW_BITMAP_RECT_TO_RECT: return "DRAW_BITMAP_RECT_TO_RECT";
59 case DRAW_CLEAR: return "DRAW_CLEAR";
60 case DRAW_DATA: return "DRAW_DATA";
61 case DRAW_OVAL: return "DRAW_OVAL";
reed@android.combcd4d5a2008-12-17 15:59:43 +000062 case DRAW_PAINT: return "DRAW_PAINT";
63 case DRAW_PATH: return "DRAW_PATH";
64 case DRAW_PICTURE: return "DRAW_PICTURE";
65 case DRAW_POINTS: return "DRAW_POINTS";
66 case DRAW_POS_TEXT: return "DRAW_POS_TEXT";
robertphillips@google.come7189be2013-02-15 17:19:15 +000067 case DRAW_POS_TEXT_TOP_BOTTOM: return "DRAW_POS_TEXT_TOP_BOTTOM";
reed@android.combcd4d5a2008-12-17 15:59:43 +000068 case DRAW_POS_TEXT_H: return "DRAW_POS_TEXT_H";
robertphillips@google.come7189be2013-02-15 17:19:15 +000069 case DRAW_POS_TEXT_H_TOP_BOTTOM: return "DRAW_POS_TEXT_H_TOP_BOTTOM";
70 case DRAW_RECT: return "DRAW_RECT";
71 case DRAW_RRECT: return "DRAW_RRECT";
reed@android.combcd4d5a2008-12-17 15:59:43 +000072 case DRAW_SPRITE: return "DRAW_SPRITE";
73 case DRAW_TEXT: return "DRAW_TEXT";
74 case DRAW_TEXT_ON_PATH: return "DRAW_TEXT_ON_PATH";
robertphillips@google.come7189be2013-02-15 17:19:15 +000075 case DRAW_TEXT_TOP_BOTTOM: return "DRAW_TEXT_TOP_BOTTOM";
76 case DRAW_VERTICES: return "DRAW_VERTICES";
reed@android.combcd4d5a2008-12-17 15:59:43 +000077 case RESTORE: return "RESTORE";
78 case ROTATE: return "ROTATE";
79 case SAVE: return "SAVE";
80 case SAVE_LAYER: return "SAVE_LAYER";
81 case SCALE: return "SCALE";
robertphillips@google.come7189be2013-02-15 17:19:15 +000082 case SET_MATRIX: return "SET_MATRIX";
reed@android.combcd4d5a2008-12-17 15:59:43 +000083 case SKEW: return "SKEW";
84 case TRANSLATE: return "TRANSLATE";
robertphillips@google.come7189be2013-02-15 17:19:15 +000085 case NOOP: return "NOOP";
reed@google.com91911482011-02-07 15:30:46 +000086 default:
87 SkDebugf("DrawType error 0x%08x\n", drawType);
88 SkASSERT(0);
reed@android.combcd4d5a2008-12-17 15:59:43 +000089 break;
90 }
reed@google.com91911482011-02-07 15:30:46 +000091 SkASSERT(0);
reed@android.combcd4d5a2008-12-17 15:59:43 +000092 return NULL;
93}
94#endif
95
96#ifdef SK_DEBUG_VALIDATE
97static void validateMatrix(const SkMatrix* matrix) {
98 SkScalar scaleX = matrix->getScaleX();
99 SkScalar scaleY = matrix->getScaleY();
100 SkScalar skewX = matrix->getSkewX();
101 SkScalar skewY = matrix->getSkewY();
102 SkScalar perspX = matrix->getPerspX();
103 SkScalar perspY = matrix->getPerspY();
104 if (scaleX != 0 && skewX != 0)
105 SkDebugf("scaleX != 0 && skewX != 0\n");
106 SkASSERT(scaleX == 0 || skewX == 0);
107 SkASSERT(scaleY == 0 || skewY == 0);
108 SkASSERT(perspX == 0);
109 SkASSERT(perspY == 0);
110}
111#endif
112
113
114///////////////////////////////////////////////////////////////////////////////
115
116SkPicture::SkPicture() {
117 fRecord = NULL;
118 fPlayback = NULL;
119 fWidth = fHeight = 0;
commit-bot@chromium.org73857a32014-03-16 19:46:36 +0000120 fAccelData = NULL;
reed@android.combcd4d5a2008-12-17 15:59:43 +0000121}
122
skia.committer@gmail.com8b5598b2014-03-17 03:02:17 +0000123SkPicture::SkPicture(const SkPicture& src)
commit-bot@chromium.org73857a32014-03-16 19:46:36 +0000124 : INHERITED()
125 , fAccelData(NULL) {
reed@android.combcd4d5a2008-12-17 15:59:43 +0000126 fWidth = src.fWidth;
127 fHeight = src.fHeight;
128 fRecord = NULL;
129
130 /* We want to copy the src's playback. However, if that hasn't been built
131 yet, we need to fake a call to endRecording() without actually calling
132 it (since it is destructive, and we don't want to change src).
133 */
134 if (src.fPlayback) {
135 fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fPlayback));
136 } else if (src.fRecord) {
137 // here we do a fake src.endRecording()
138 fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fRecord));
139 } else {
140 fPlayback = NULL;
141 }
142}
143
144SkPicture::~SkPicture() {
reed@google.com91911482011-02-07 15:30:46 +0000145 SkSafeUnref(fRecord);
reed@android.combcd4d5a2008-12-17 15:59:43 +0000146 SkDELETE(fPlayback);
commit-bot@chromium.org73857a32014-03-16 19:46:36 +0000147 SkSafeUnref(fAccelData);
reed@android.combcd4d5a2008-12-17 15:59:43 +0000148}
149
commit-bot@chromium.orge6e785e2014-03-04 19:08:57 +0000150void SkPicture::internalOnly_EnableOpts(bool enableOpts) {
151 if (NULL != fRecord) {
152 fRecord->internalOnly_EnableOpts(enableOpts);
153 }
154}
155
reed@android.combcd4d5a2008-12-17 15:59:43 +0000156void SkPicture::swap(SkPicture& other) {
157 SkTSwap(fRecord, other.fRecord);
158 SkTSwap(fPlayback, other.fPlayback);
commit-bot@chromium.org73857a32014-03-16 19:46:36 +0000159 SkTSwap(fAccelData, other.fAccelData);
reed@android.combcd4d5a2008-12-17 15:59:43 +0000160 SkTSwap(fWidth, other.fWidth);
161 SkTSwap(fHeight, other.fHeight);
162}
163
djsollen@google.com3855f872012-08-29 18:52:07 +0000164SkPicture* SkPicture::clone() const {
165 SkPicture* clonedPicture = SkNEW(SkPicture);
166 clone(clonedPicture, 1);
167 return clonedPicture;
168}
169
170void SkPicture::clone(SkPicture* pictures, int count) const {
171 SkPictCopyInfo copyInfo;
172
173 for (int i = 0; i < count; i++) {
174 SkPicture* clone = &pictures[i];
175
176 clone->fWidth = fWidth;
177 clone->fHeight = fHeight;
commit-bot@chromium.orgefea6992014-02-14 17:27:10 +0000178 SkSafeSetNull(clone->fRecord);
scroggo@google.coma0dd4332012-11-02 20:51:19 +0000179 SkDELETE(clone->fPlayback);
180
djsollen@google.com3855f872012-08-29 18:52:07 +0000181 /* We want to copy the src's playback. However, if that hasn't been built
182 yet, we need to fake a call to endRecording() without actually calling
183 it (since it is destructive, and we don't want to change src).
184 */
185 if (fPlayback) {
186 clone->fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fPlayback, &copyInfo));
187 } else if (fRecord) {
188 // here we do a fake src.endRecording()
189 clone->fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fRecord, true));
190 } else {
191 clone->fPlayback = NULL;
192 }
193 }
194}
195
commit-bot@chromium.org73857a32014-03-16 19:46:36 +0000196SkPicture::AccelData::Domain SkPicture::AccelData::GenerateDomain() {
197 static int32_t gNextID = 0;
198
199 int32_t id = sk_atomic_inc(&gNextID);
200 if (id >= 1 << (8 * sizeof(Domain))) {
201 SK_CRASH();
202 }
203
204 return static_cast<Domain>(id);
205}
206
reed@android.combcd4d5a2008-12-17 15:59:43 +0000207///////////////////////////////////////////////////////////////////////////////
208
reed@android.comc4a55d72009-02-13 14:56:09 +0000209SkCanvas* SkPicture::beginRecording(int width, int height,
210 uint32_t recordingFlags) {
reed@android.combcd4d5a2008-12-17 15:59:43 +0000211 if (fPlayback) {
212 SkDELETE(fPlayback);
213 fPlayback = NULL;
214 }
commit-bot@chromium.org73857a32014-03-16 19:46:36 +0000215 SkSafeUnref(fAccelData);
commit-bot@chromium.orgefea6992014-02-14 17:27:10 +0000216 SkSafeSetNull(fRecord);
reed@android.combcd4d5a2008-12-17 15:59:43 +0000217
junov@chromium.orgbb78c442012-11-01 17:10:32 +0000218 // Must be set before calling createBBoxHierarchy
219 fWidth = width;
220 fHeight = height;
221
commit-bot@chromium.orgca101d62014-02-17 15:28:00 +0000222 const SkISize size = SkISize::Make(width, height);
223
rileya@google.com7fb3d2f2012-09-13 21:41:51 +0000224 if (recordingFlags & kOptimizeForClippedPlayback_RecordingFlag) {
junov@chromium.orgbb78c442012-11-01 17:10:32 +0000225 SkBBoxHierarchy* tree = this->createBBoxHierarchy();
rileya@google.com7fb3d2f2012-09-13 21:41:51 +0000226 SkASSERT(NULL != tree);
commit-bot@chromium.orgca101d62014-02-17 15:28:00 +0000227 fRecord = SkNEW_ARGS(SkBBoxHierarchyRecord, (size, recordingFlags, tree));
rileya@google.com7fb3d2f2012-09-13 21:41:51 +0000228 tree->unref();
229 } else {
commit-bot@chromium.orgca101d62014-02-17 15:28:00 +0000230 fRecord = SkNEW_ARGS(SkPictureRecord, (size, recordingFlags));
rileya@google.com7fb3d2f2012-09-13 21:41:51 +0000231 }
reed@google.com118a6d02012-09-27 20:31:31 +0000232 fRecord->beginRecording();
reed@android.combcd4d5a2008-12-17 15:59:43 +0000233
reed@android.combcd4d5a2008-12-17 15:59:43 +0000234 return fRecord;
235}
236
junov@chromium.orgbb78c442012-11-01 17:10:32 +0000237SkBBoxHierarchy* SkPicture::createBBoxHierarchy() const {
skia.committer@gmail.com8d230dd2012-11-02 02:01:24 +0000238 // These values were empirically determined to produce reasonable
junov@chromium.orgbb78c442012-11-01 17:10:32 +0000239 // performance in most cases.
240 static const int kRTreeMinChildren = 6;
241 static const int kRTreeMaxChildren = 11;
242
243 SkScalar aspectRatio = SkScalarDiv(SkIntToScalar(fWidth),
244 SkIntToScalar(fHeight));
sglez@google.com9baab6f2013-08-30 17:27:47 +0000245 bool sortDraws = false; // Do not sort draw calls when bulk loading.
246
junov@chromium.orgbb78c442012-11-01 17:10:32 +0000247 return SkRTree::Create(kRTreeMinChildren, kRTreeMaxChildren,
sglez@google.com9baab6f2013-08-30 17:27:47 +0000248 aspectRatio, sortDraws);
junov@chromium.orgbb78c442012-11-01 17:10:32 +0000249}
250
reed@android.combcd4d5a2008-12-17 15:59:43 +0000251SkCanvas* SkPicture::getRecordingCanvas() const {
252 // will be null if we are not recording
253 return fRecord;
254}
255
256void SkPicture::endRecording() {
257 if (NULL == fPlayback) {
258 if (NULL != fRecord) {
junov@chromium.org9aa18db2012-07-12 17:47:34 +0000259 fRecord->endRecording();
reed@android.combcd4d5a2008-12-17 15:59:43 +0000260 fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fRecord));
commit-bot@chromium.orgefea6992014-02-14 17:27:10 +0000261 SkSafeSetNull(fRecord);
reed@android.combcd4d5a2008-12-17 15:59:43 +0000262 }
263 }
264 SkASSERT(NULL == fRecord);
265}
266
commit-bot@chromium.org4b918972014-03-18 17:45:32 +0000267const SkPicture::OperationList& SkPicture::OperationList::InvalidList() {
268 static OperationList gInvalid;
269 return gInvalid;
270}
271
272const SkPicture::OperationList& SkPicture::EXPERIMENTAL_getActiveOps(const SkIRect& queryRect) {
273 this->endRecording();
274 if (NULL != fPlayback) {
275 return fPlayback->getActiveOps(queryRect);
276 }
277 return OperationList::InvalidList();
278}
279
reed@google.com2b3a5082013-05-20 17:02:41 +0000280void SkPicture::draw(SkCanvas* surface, SkDrawPictureCallback* callback) {
reed@android.combcd4d5a2008-12-17 15:59:43 +0000281 this->endRecording();
commit-bot@chromium.org73857a32014-03-16 19:46:36 +0000282 if (NULL != fPlayback) {
reed@google.com2b3a5082013-05-20 17:02:41 +0000283 fPlayback->draw(*surface, callback);
reed@android.combcd4d5a2008-12-17 15:59:43 +0000284 }
285}
286
287///////////////////////////////////////////////////////////////////////////////
288
289#include "SkStream.h"
290
rmistry@google.com8793ad72013-12-02 13:50:38 +0000291static const char kMagic[] = { 's', 'k', 'i', 'a', 'p', 'i', 'c', 't' };
commit-bot@chromium.org060e3a52014-03-12 14:46:41 +0000292
293bool SkPicture::IsValidPictInfo(const SkPictInfo& info) {
294 if (0 != memcmp(info.fMagic, kMagic, sizeof(kMagic))) {
295 return false;
296 }
297
298 if (info.fVersion < MIN_PICTURE_VERSION ||
299 info.fVersion > CURRENT_PICTURE_VERSION) {
300 return false;
301 }
302
303 return true;
304}
rmistry@google.com8793ad72013-12-02 13:50:38 +0000305
commit-bot@chromium.orgabad6d62014-03-03 19:18:39 +0000306bool SkPicture::InternalOnly_StreamIsSKP(SkStream* stream, SkPictInfo* pInfo) {
scroggo@google.com3b990302013-06-28 21:32:00 +0000307 if (NULL == stream) {
308 return false;
borenet@google.com30dda202012-09-17 18:26:06 +0000309 }
reed@google.com4bca7f62012-06-22 15:38:39 +0000310
rmistry@google.com8793ad72013-12-02 13:50:38 +0000311 // Check magic bytes.
reed@google.com4bca7f62012-06-22 15:38:39 +0000312 SkPictInfo info;
commit-bot@chromium.org060e3a52014-03-12 14:46:41 +0000313 SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
314 if (!stream->read(&info, sizeof(info)) || !IsValidPictInfo(info)) {
scroggo@google.com3b990302013-06-28 21:32:00 +0000315 return false;
reed@google.com4bca7f62012-06-22 15:38:39 +0000316 }
reed@android.combcd4d5a2008-12-17 15:59:43 +0000317
scroggo@google.com3b990302013-06-28 21:32:00 +0000318 if (pInfo != NULL) {
319 *pInfo = info;
320 }
321 return true;
322}
323
commit-bot@chromium.orgabad6d62014-03-03 19:18:39 +0000324bool SkPicture::InternalOnly_BufferIsSKP(SkReadBuffer& buffer, SkPictInfo* pInfo) {
commit-bot@chromium.org7183ff62014-02-07 12:20:04 +0000325 // Check magic bytes.
commit-bot@chromium.org7183ff62014-02-07 12:20:04 +0000326 SkPictInfo info;
commit-bot@chromium.org060e3a52014-03-12 14:46:41 +0000327 SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
328 if (!buffer.readByteArray(&info, sizeof(info)) || !IsValidPictInfo(info)) {
commit-bot@chromium.org7183ff62014-02-07 12:20:04 +0000329 return false;
330 }
331
332 if (pInfo != NULL) {
333 *pInfo = info;
334 }
335 return true;
336}
337
scroggo@google.com3b990302013-06-28 21:32:00 +0000338SkPicture::SkPicture(SkPicturePlayback* playback, int width, int height)
339 : fPlayback(playback)
340 , fRecord(NULL)
341 , fWidth(width)
commit-bot@chromium.org73857a32014-03-16 19:46:36 +0000342 , fHeight(height)
343 , fAccelData(NULL) {}
scroggo@google.com3b990302013-06-28 21:32:00 +0000344
345SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc proc) {
346 SkPictInfo info;
347
commit-bot@chromium.orgabad6d62014-03-03 19:18:39 +0000348 if (!InternalOnly_StreamIsSKP(stream, &info)) {
scroggo@google.com3b990302013-06-28 21:32:00 +0000349 return NULL;
350 }
351
352 SkPicturePlayback* playback;
353 // Check to see if there is a playback to recreate.
reed@android.combcd4d5a2008-12-17 15:59:43 +0000354 if (stream->readBool()) {
scroggo@google.com3b7431c2013-10-01 15:30:46 +0000355 playback = SkPicturePlayback::CreateFromStream(stream, info, proc);
356 if (NULL == playback) {
357 return NULL;
358 }
scroggo@google.com3b990302013-06-28 21:32:00 +0000359 } else {
360 playback = NULL;
reed@android.combcd4d5a2008-12-17 15:59:43 +0000361 }
reed@google.com4bca7f62012-06-22 15:38:39 +0000362
scroggo@google.com3b990302013-06-28 21:32:00 +0000363 return SkNEW_ARGS(SkPicture, (playback, info.fWidth, info.fHeight));
reed@android.combcd4d5a2008-12-17 15:59:43 +0000364}
365
commit-bot@chromium.org7183ff62014-02-07 12:20:04 +0000366SkPicture* SkPicture::CreateFromBuffer(SkReadBuffer& buffer) {
367 SkPictInfo info;
368
commit-bot@chromium.orgabad6d62014-03-03 19:18:39 +0000369 if (!InternalOnly_BufferIsSKP(buffer, &info)) {
commit-bot@chromium.org7183ff62014-02-07 12:20:04 +0000370 return NULL;
371 }
372
373 SkPicturePlayback* playback;
374 // Check to see if there is a playback to recreate.
375 if (buffer.readBool()) {
376 playback = SkPicturePlayback::CreateFromBuffer(buffer);
377 if (NULL == playback) {
378 return NULL;
379 }
380 } else {
381 playback = NULL;
382 }
383
384 return SkNEW_ARGS(SkPicture, (playback, info.fWidth, info.fHeight));
385}
386
commit-bot@chromium.org060e3a52014-03-12 14:46:41 +0000387void SkPicture::createHeader(SkPictInfo* info) const {
commit-bot@chromium.org7183ff62014-02-07 12:20:04 +0000388 // Copy magic bytes at the beginning of the header
389 SkASSERT(sizeof(kMagic) == 8);
commit-bot@chromium.org060e3a52014-03-12 14:46:41 +0000390 SkASSERT(sizeof(kMagic) == sizeof(info->fMagic));
391 memcpy(info->fMagic, kMagic, sizeof(kMagic));
commit-bot@chromium.org7183ff62014-02-07 12:20:04 +0000392
commit-bot@chromium.orgabad6d62014-03-03 19:18:39 +0000393 // Set picture info after magic bytes in the header
commit-bot@chromium.org338284f2014-02-25 02:16:10 +0000394 info->fVersion = CURRENT_PICTURE_VERSION;
commit-bot@chromium.org7183ff62014-02-07 12:20:04 +0000395 info->fWidth = fWidth;
396 info->fHeight = fHeight;
397 info->fFlags = SkPictInfo::kCrossProcess_Flag;
398 // TODO: remove this flag, since we're always float (now)
399 info->fFlags |= SkPictInfo::kScalarIsFloat_Flag;
400
401 if (8 == sizeof(void*)) {
402 info->fFlags |= SkPictInfo::kPtrIs64Bit_Flag;
403 }
404}
405
scroggo@google.com2e727312013-02-22 22:04:19 +0000406void SkPicture::serialize(SkWStream* stream, EncodeBitmap encoder) const {
reed@android.combcd4d5a2008-12-17 15:59:43 +0000407 SkPicturePlayback* playback = fPlayback;
reed@google.com91911482011-02-07 15:30:46 +0000408
reed@android.combcd4d5a2008-12-17 15:59:43 +0000409 if (NULL == playback && fRecord) {
410 playback = SkNEW_ARGS(SkPicturePlayback, (*fRecord));
411 }
412
commit-bot@chromium.org060e3a52014-03-12 14:46:41 +0000413 SkPictInfo header;
commit-bot@chromium.orgabad6d62014-03-03 19:18:39 +0000414 this->createHeader(&header);
commit-bot@chromium.org060e3a52014-03-12 14:46:41 +0000415 stream->write(&header, sizeof(header));
reed@android.combcd4d5a2008-12-17 15:59:43 +0000416 if (playback) {
417 stream->writeBool(true);
scroggo@google.com6ff73172012-10-04 21:46:08 +0000418 playback->serialize(stream, encoder);
reed@android.combcd4d5a2008-12-17 15:59:43 +0000419 // delete playback if it is a local version (i.e. cons'd up just now)
420 if (playback != fPlayback) {
421 SkDELETE(playback);
422 }
423 } else {
424 stream->writeBool(false);
425 }
426}
427
commit-bot@chromium.org7183ff62014-02-07 12:20:04 +0000428void SkPicture::flatten(SkWriteBuffer& buffer) const {
429 SkPicturePlayback* playback = fPlayback;
430
431 if (NULL == playback && fRecord) {
432 playback = SkNEW_ARGS(SkPicturePlayback, (*fRecord));
433 }
434
commit-bot@chromium.org060e3a52014-03-12 14:46:41 +0000435 SkPictInfo header;
commit-bot@chromium.orgabad6d62014-03-03 19:18:39 +0000436 this->createHeader(&header);
commit-bot@chromium.org060e3a52014-03-12 14:46:41 +0000437 buffer.writeByteArray(&header, sizeof(header));
commit-bot@chromium.org7183ff62014-02-07 12:20:04 +0000438 if (playback) {
439 buffer.writeBool(true);
440 playback->flatten(buffer);
441 // delete playback if it is a local version (i.e. cons'd up just now)
442 if (playback != fPlayback) {
443 SkDELETE(playback);
444 }
445 } else {
446 buffer.writeBool(false);
447 }
448}
449
tomhudson@google.comc7941702013-10-24 11:12:47 +0000450bool SkPicture::willPlayBackBitmaps() const {
commit-bot@chromium.org73857a32014-03-16 19:46:36 +0000451 if (!fPlayback) {
452 return false;
453 }
tomhudson@google.comc7941702013-10-24 11:12:47 +0000454 return fPlayback->containsBitmaps();
455}
456
djsollen@google.com6789a342013-02-01 16:18:09 +0000457#ifdef SK_BUILD_FOR_ANDROID
reed@android.combcd4d5a2008-12-17 15:59:43 +0000458void SkPicture::abortPlayback() {
459 if (NULL == fPlayback) {
460 return;
461 }
462 fPlayback->abort();
463}
djsollen@google.com6789a342013-02-01 16:18:09 +0000464#endif