blob: 35e66bb7eb360c38ac6ea7baf4a1107d043a141d [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
reed@android.com8a1c16f2008-12-17 15:59:43 +00007#include <new>
rileya@google.com8515e792012-09-13 21:41:51 +00008#include "SkBBoxHierarchy.h"
Mike Kleinc11530e2014-06-24 11:29:06 -04009#include "SkDrawPictureCallback.h"
commit-bot@chromium.org8016f792014-03-07 15:53:01 +000010#include "SkPicturePlayback.h"
11#include "SkPictureRecord.h"
rileya@google.com8515e792012-09-13 21:41:51 +000012#include "SkPictureStateTree.h"
commit-bot@chromium.org8016f792014-03-07 15:53:01 +000013#include "SkReadBuffer.h"
14#include "SkTypeface.h"
rileya@google.com8515e792012-09-13 21:41:51 +000015#include "SkTSort.h"
commit-bot@chromium.org8016f792014-03-07 15:53:01 +000016#include "SkWriteBuffer.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000017
egdaniel12c21982014-06-18 07:34:39 -070018#if SK_SUPPORT_GPU
19#include "GrContext.h"
20#endif
21
reed@google.comf4cc1872012-07-23 15:04:45 +000022template <typename T> int SafeCount(const T* obj) {
23 return obj ? obj->count() : 0;
24}
25
reed@android.comae814c82009-02-13 14:56:09 +000026/* Define this to spew out a debug statement whenever we skip the remainder of
27 a save/restore block because a clip... command returned false (empty).
28 */
29#define SPEW_CLIP_SKIPPINGx
30
skia.committer@gmail.comb2c82c92014-05-08 03:05:29 +000031SkPicturePlayback::PlaybackReplacements::ReplacementInfo*
32SkPicturePlayback::PlaybackReplacements::push() {
robertphillips@google.combeb1af22014-05-07 21:31:09 +000033 SkDEBUGCODE(this->validate());
skia.committer@gmail.comb2c82c92014-05-08 03:05:29 +000034 return fReplacements.push();
robertphillips@google.combeb1af22014-05-07 21:31:09 +000035}
36
37void SkPicturePlayback::PlaybackReplacements::freeAll() {
38 for (int i = 0; i < fReplacements.count(); ++i) {
39 SkDELETE(fReplacements[i].fBM);
40 }
41 fReplacements.reset();
42}
43
44#ifdef SK_DEBUG
45void SkPicturePlayback::PlaybackReplacements::validate() const {
46 // Check that the ranges are monotonically increasing and non-overlapping
47 if (fReplacements.count() > 0) {
48 SkASSERT(fReplacements[0].fStart < fReplacements[0].fStop);
49
50 for (int i = 1; i < fReplacements.count(); ++i) {
51 SkASSERT(fReplacements[i].fStart < fReplacements[i].fStop);
52 SkASSERT(fReplacements[i-1].fStop < fReplacements[i].fStart);
53 }
54 }
55}
56#endif
57
robertphillipse26e65e2014-06-12 05:51:22 -070058SkPicturePlayback::SkPicturePlayback(const SkPictInfo& info)
59 : fInfo(info) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000060 this->init();
61}
62
robertphillipse26e65e2014-06-12 05:51:22 -070063void SkPicturePlayback::initForPlayback() const {
64 // ensure that the paths bounds are pre-computed
65 if (NULL != fPathHeap.get()) {
66 for (int i = 0; i < fPathHeap->count(); i++) {
67 (*fPathHeap.get())[i].updateBoundsCache();
68 }
69 }
70}
71
72SkPicturePlayback::SkPicturePlayback(const SkPictureRecord& record,
robertphillips9058d602014-06-10 11:45:46 -070073 const SkPictInfo& info,
74 bool deepCopyOps)
robertphillipse26e65e2014-06-12 05:51:22 -070075 : fInfo(info) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000076#ifdef SK_DEBUG_SIZE
reed@google.com82065d62011-02-07 15:30:46 +000077 size_t overallBytes, bitmapBytes, matricesBytes,
reed@android.com8a1c16f2008-12-17 15:59:43 +000078 paintBytes, pathBytes, pictureBytes, regionBytes;
79 int bitmaps = record.bitmaps(&bitmapBytes);
80 int matrices = record.matrices(&matricesBytes);
81 int paints = record.paints(&paintBytes);
82 int paths = record.paths(&pathBytes);
83 int pictures = record.pictures(&pictureBytes);
84 int regions = record.regions(&regionBytes);
85 SkDebugf("picture record mem used %zd (stream %zd) ", record.size(),
86 record.streamlen());
87 if (bitmaps != 0)
88 SkDebugf("bitmaps size %zd (bitmaps:%d) ", bitmapBytes, bitmaps);
89 if (matrices != 0)
90 SkDebugf("matrices size %zd (matrices:%d) ", matricesBytes, matrices);
91 if (paints != 0)
92 SkDebugf("paints size %zd (paints:%d) ", paintBytes, paints);
93 if (paths != 0)
94 SkDebugf("paths size %zd (paths:%d) ", pathBytes, paths);
95 if (pictures != 0)
96 SkDebugf("pictures size %zd (pictures:%d) ", pictureBytes, pictures);
97 if (regions != 0)
98 SkDebugf("regions size %zd (regions:%d) ", regionBytes, regions);
99 if (record.fPointWrites != 0)
100 SkDebugf("points size %zd (points:%d) ", record.fPointBytes, record.fPointWrites);
101 if (record.fRectWrites != 0)
102 SkDebugf("rects size %zd (rects:%d) ", record.fRectBytes, record.fRectWrites);
103 if (record.fTextWrites != 0)
104 SkDebugf("text size %zd (text strings:%d) ", record.fTextBytes, record.fTextWrites);
reed@google.com82065d62011-02-07 15:30:46 +0000105
reed@android.com8a1c16f2008-12-17 15:59:43 +0000106 SkDebugf("\n");
107#endif
108#ifdef SK_DEBUG_DUMP
109 record.dumpMatrices();
110 record.dumpPaints();
111#endif
112
commit-bot@chromium.org70512af2014-03-18 17:45:32 +0000113 this->init();
robertphillips0bdbea72014-06-11 11:37:55 -0700114
115 fOpData = record.opData(deepCopyOps);
reed@google.com82065d62011-02-07 15:30:46 +0000116
rileya@google.com8515e792012-09-13 21:41:51 +0000117 fBoundingHierarchy = record.fBoundingHierarchy;
118 fStateTree = record.fStateTree;
119
120 SkSafeRef(fBoundingHierarchy);
121 SkSafeRef(fStateTree);
robertphillips0bdbea72014-06-11 11:37:55 -0700122 fContentInfo.set(record.fContentInfo);
rileya@google.com8515e792012-09-13 21:41:51 +0000123
124 if (NULL != fBoundingHierarchy) {
125 fBoundingHierarchy->flushDeferredInserts();
126 }
127
reed@android.com8a1c16f2008-12-17 15:59:43 +0000128 // copy over the refcnt dictionary to our reader
djsollen@google.com21830d92012-08-07 19:49:41 +0000129 record.fFlattenableHeap.setupPlaybacks();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000130
djsollen@google.comc9ab9872012-08-29 18:52:07 +0000131 fBitmaps = record.fBitmapHeap->extractBitmaps();
djsollen@google.com21830d92012-08-07 19:49:41 +0000132 fPaints = record.fPaints.unflattenToArray();
djsollen@google.com21830d92012-08-07 19:49:41 +0000133
djsollen@google.comc9ab9872012-08-29 18:52:07 +0000134 fBitmapHeap.reset(SkSafeRef(record.fBitmapHeap));
robertphillipse26e65e2014-06-12 05:51:22 -0700135 fPathHeap.reset(SkSafeRef(record.pathHeap()));
djsollen@google.comc9ab9872012-08-29 18:52:07 +0000136
robertphillipse26e65e2014-06-12 05:51:22 -0700137 this->initForPlayback();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000138
robertphillips9b14f262014-06-04 05:40:44 -0700139 const SkTDArray<const SkPicture* >& pictures = record.getPictureRefs();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000140 fPictureCount = pictures.count();
141 if (fPictureCount > 0) {
robertphillips9b14f262014-06-04 05:40:44 -0700142 fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000143 for (int i = 0; i < fPictureCount; i++) {
robertphillips6de27122014-06-10 09:23:06 -0700144 fPictureRefs[i] = pictures[i];
145 fPictureRefs[i]->ref();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000146 }
147 }
reed@google.com82065d62011-02-07 15:30:46 +0000148
reed@android.com8a1c16f2008-12-17 15:59:43 +0000149#ifdef SK_DEBUG_SIZE
150 int overall = fPlayback->size(&overallBytes);
151 bitmaps = fPlayback->bitmaps(&bitmapBytes);
152 paints = fPlayback->paints(&paintBytes);
153 paths = fPlayback->paths(&pathBytes);
154 pictures = fPlayback->pictures(&pictureBytes);
155 regions = fPlayback->regions(&regionBytes);
156 SkDebugf("playback size %zd (objects:%d) ", overallBytes, overall);
157 if (bitmaps != 0)
158 SkDebugf("bitmaps size %zd (bitmaps:%d) ", bitmapBytes, bitmaps);
159 if (paints != 0)
160 SkDebugf("paints size %zd (paints:%d) ", paintBytes, paints);
161 if (paths != 0)
162 SkDebugf("paths size %zd (paths:%d) ", pathBytes, paths);
163 if (pictures != 0)
164 SkDebugf("pictures size %zd (pictures:%d) ", pictureBytes, pictures);
165 if (regions != 0)
166 SkDebugf("regions size %zd (regions:%d) ", regionBytes, regions);
167 SkDebugf("\n");
168#endif
169}
170
mtkleind3e474e2014-06-27 12:34:44 -0700171#ifdef SK_SUPPORT_LEGACY_PICTURE_CLONE
robertphillipse26e65e2014-06-12 05:51:22 -0700172SkPicturePlayback::SkPicturePlayback(const SkPicturePlayback& src, SkPictCopyInfo* deepCopyInfo)
173 : fInfo(src.fInfo) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000174 this->init();
175
djsollen@google.comc9ab9872012-08-29 18:52:07 +0000176 fBitmapHeap.reset(SkSafeRef(src.fBitmapHeap.get()));
robertphillipse26e65e2014-06-12 05:51:22 -0700177 fPathHeap.reset(SkSafeRef(src.fPathHeap.get()));
djsollen@google.comc9ab9872012-08-29 18:52:07 +0000178
djsollen@google.comc9ab9872012-08-29 18:52:07 +0000179 fOpData = SkSafeRef(src.fOpData);
skia.committer@gmail.com1d225f22012-09-14 02:01:10 +0000180
rileya@google.com8515e792012-09-13 21:41:51 +0000181 fBoundingHierarchy = src.fBoundingHierarchy;
182 fStateTree = src.fStateTree;
robertphillips0bdbea72014-06-11 11:37:55 -0700183 fContentInfo.set(src.fContentInfo);
rileya@google.com8515e792012-09-13 21:41:51 +0000184
185 SkSafeRef(fBoundingHierarchy);
186 SkSafeRef(fStateTree);
djsollen@google.comc9ab9872012-08-29 18:52:07 +0000187
188 if (deepCopyInfo) {
commit-bot@chromium.org66ec1e42014-04-29 17:22:54 +0000189 SkASSERT(deepCopyInfo->initialized);
190
junov@chromium.org94f20dc2013-01-28 21:04:44 +0000191 int paintCount = SafeCount(src.fPaints);
djsollen@google.comc9ab9872012-08-29 18:52:07 +0000192
193 if (src.fBitmaps) {
194 fBitmaps = SkTRefArray<SkBitmap>::Create(src.fBitmaps->begin(), src.fBitmaps->count());
195 }
196
junov@chromium.org94f20dc2013-01-28 21:04:44 +0000197 fPaints = SkTRefArray<SkPaint>::Create(paintCount);
198 SkASSERT(deepCopyInfo->paintData.count() == paintCount);
reed@google.comdee54be2012-12-10 17:39:36 +0000199 SkBitmapHeap* bmHeap = deepCopyInfo->controller.getBitmapHeap();
200 SkTypefacePlayback* tfPlayback = deepCopyInfo->controller.getTypefacePlayback();
junov@chromium.org94f20dc2013-01-28 21:04:44 +0000201 for (int i = 0; i < paintCount; i++) {
reed@google.comdee54be2012-12-10 17:39:36 +0000202 if (deepCopyInfo->paintData[i]) {
commit-bot@chromium.orgaca1c012014-02-21 18:18:05 +0000203 deepCopyInfo->paintData[i]->unflatten<SkPaint::FlatteningTraits>(
204 &fPaints->writableAt(i), bmHeap, tfPlayback);
reed@google.comdee54be2012-12-10 17:39:36 +0000205 } else {
206 // needs_deep_copy was false, so just need to assign
207 fPaints->writableAt(i) = src.fPaints->at(i);
208 }
djsollen@google.comc9ab9872012-08-29 18:52:07 +0000209 }
210
211 } else {
212 fBitmaps = SkSafeRef(src.fBitmaps);
213 fPaints = SkSafeRef(src.fPaints);
214 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000215
216 fPictureCount = src.fPictureCount;
robertphillips9b14f262014-06-04 05:40:44 -0700217 fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000218 for (int i = 0; i < fPictureCount; i++) {
djsollen@google.comc9ab9872012-08-29 18:52:07 +0000219 if (deepCopyInfo) {
220 fPictureRefs[i] = src.fPictureRefs[i]->clone();
221 } else {
222 fPictureRefs[i] = src.fPictureRefs[i];
223 fPictureRefs[i]->ref();
224 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000225 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000226}
mtkleind3e474e2014-06-27 12:34:44 -0700227#else
228SkPicturePlayback::SkPicturePlayback(const SkPicturePlayback& src) : fInfo(src.fInfo) {
229 this->init();
230
231 fBitmapHeap.reset(SkSafeRef(src.fBitmapHeap.get()));
232 fPathHeap.reset(SkSafeRef(src.fPathHeap.get()));
233
234 fOpData = SkSafeRef(src.fOpData);
235
236 fBoundingHierarchy = src.fBoundingHierarchy;
237 fStateTree = src.fStateTree;
238 fContentInfo.set(src.fContentInfo);
239
240 SkSafeRef(fBoundingHierarchy);
241 SkSafeRef(fStateTree);
242
243 fBitmaps = SkSafeRef(src.fBitmaps);
244 fPaints = SkSafeRef(src.fPaints);
245
246 fPictureCount = src.fPictureCount;
247 fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount);
248 for (int i = 0; i < fPictureCount; i++) {
249 fPictureRefs[i] = SkRef(src.fPictureRefs[i]);
250 }
251}
252#endif//SK_SUPPORT_LEGACY_PICTURE_CLONE
reed@android.com8a1c16f2008-12-17 15:59:43 +0000253
254void SkPicturePlayback::init() {
255 fBitmaps = NULL;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000256 fPaints = NULL;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000257 fPictureRefs = NULL;
reed@google.comf4cc1872012-07-23 15:04:45 +0000258 fPictureCount = 0;
reed@google.comddf98a82012-07-21 20:31:09 +0000259 fOpData = NULL;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000260 fFactoryPlayback = NULL;
rileya@google.com8515e792012-09-13 21:41:51 +0000261 fBoundingHierarchy = NULL;
262 fStateTree = NULL;
commit-bot@chromium.org70512af2014-03-18 17:45:32 +0000263 fCachedActiveOps = NULL;
commit-bot@chromium.org75cf29b2014-03-24 19:40:49 +0000264 fCurOffset = 0;
robertphillips@google.combeb1af22014-05-07 21:31:09 +0000265 fUseBBH = true;
266 fStart = 0;
267 fStop = 0;
268 fReplacements = NULL;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000269}
270
271SkPicturePlayback::~SkPicturePlayback() {
commit-bot@chromium.org9e5f85e2014-03-12 14:46:41 +0000272 SkSafeUnref(fOpData);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000273
reed@google.comf4cc1872012-07-23 15:04:45 +0000274 SkSafeUnref(fBitmaps);
reed@google.comf4cc1872012-07-23 15:04:45 +0000275 SkSafeUnref(fPaints);
rileya@google.com8515e792012-09-13 21:41:51 +0000276 SkSafeUnref(fBoundingHierarchy);
277 SkSafeUnref(fStateTree);
reed@google.com82065d62011-02-07 15:30:46 +0000278
commit-bot@chromium.org70512af2014-03-18 17:45:32 +0000279 SkDELETE(fCachedActiveOps);
280
reed@android.com8a1c16f2008-12-17 15:59:43 +0000281 for (int i = 0; i < fPictureCount; i++) {
282 fPictureRefs[i]->unref();
283 }
284 SkDELETE_ARRAY(fPictureRefs);
reed@google.com82065d62011-02-07 15:30:46 +0000285
reed@android.com8a1c16f2008-12-17 15:59:43 +0000286 SkDELETE(fFactoryPlayback);
287}
288
289void SkPicturePlayback::dumpSize() const {
commit-bot@chromium.org8f831f22014-04-23 22:35:42 +0000290 SkDebugf("--- picture size: ops=%d bitmaps=%d [%d] paints=%d [%d]\n",
reed@google.comddf98a82012-07-21 20:31:09 +0000291 fOpData->size(),
reed@google.comf4cc1872012-07-23 15:04:45 +0000292 SafeCount(fBitmaps), SafeCount(fBitmaps) * sizeof(SkBitmap),
commit-bot@chromium.org8f831f22014-04-23 22:35:42 +0000293 SafeCount(fPaints), SafeCount(fPaints) * sizeof(SkPaint));
robertphillipse26e65e2014-06-12 05:51:22 -0700294 SkDebugf("--- picture size: paths=%d\n",
295 SafeCount(fPathHeap.get()));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000296}
297
tomhudson@google.com381010e2013-10-24 11:12:47 +0000298bool SkPicturePlayback::containsBitmaps() const {
299 if (fBitmaps && fBitmaps->count() > 0) {
300 return true;
301 }
302 for (int i = 0; i < fPictureCount; ++i) {
303 if (fPictureRefs[i]->willPlayBackBitmaps()) {
304 return true;
305 }
306 }
307 return false;
308}
309
reed@android.com8a1c16f2008-12-17 15:59:43 +0000310///////////////////////////////////////////////////////////////////////////////
311///////////////////////////////////////////////////////////////////////////////
312
reed@android.com8a1c16f2008-12-17 15:59:43 +0000313#include "SkStream.h"
314
commit-bot@chromium.orgdcb8e542014-03-05 18:25:20 +0000315static size_t compute_chunk_size(SkFlattenable::Factory* array, int count) {
316 size_t size = 4; // for 'count'
reed@google.com82065d62011-02-07 15:30:46 +0000317
commit-bot@chromium.orgdcb8e542014-03-05 18:25:20 +0000318 for (int i = 0; i < count; i++) {
319 const char* name = SkFlattenable::FactoryToName(array[i]);
320 if (NULL == name || 0 == *name) {
321 size += SkWStream::SizeOfPackedUInt(0);
322 } else {
323 size_t len = strlen(name);
324 size += SkWStream::SizeOfPackedUInt(len);
325 size += len;
326 }
327 }
328
329 return size;
330}
331
commit-bot@chromium.org8f831f22014-04-23 22:35:42 +0000332void SkPicturePlayback::WriteFactories(SkWStream* stream, const SkFactorySet& rec) {
commit-bot@chromium.orgdcb8e542014-03-05 18:25:20 +0000333 int count = rec.count();
reed@google.com82065d62011-02-07 15:30:46 +0000334
reed@android.com8a1c16f2008-12-17 15:59:43 +0000335 SkAutoSTMalloc<16, SkFlattenable::Factory> storage(count);
336 SkFlattenable::Factory* array = (SkFlattenable::Factory*)storage.get();
mike@reedtribe.orge9e08cc2011-04-29 01:44:52 +0000337 rec.copyToArray(array);
reed@google.com82065d62011-02-07 15:30:46 +0000338
commit-bot@chromium.orgdcb8e542014-03-05 18:25:20 +0000339 size_t size = compute_chunk_size(array, count);
340
341 // TODO: write_tag_size should really take a size_t
commit-bot@chromium.org8f831f22014-04-23 22:35:42 +0000342 SkPicture::WriteTagSize(stream, SK_PICT_FACTORY_TAG, (uint32_t) size);
commit-bot@chromium.org06e97522014-03-06 20:53:44 +0000343 SkDEBUGCODE(size_t start = stream->bytesWritten());
commit-bot@chromium.orgdcb8e542014-03-05 18:25:20 +0000344 stream->write32(count);
345
reed@android.com8a1c16f2008-12-17 15:59:43 +0000346 for (int i = 0; i < count; i++) {
347 const char* name = SkFlattenable::FactoryToName(array[i]);
348// SkDebugf("---- write factories [%d] %p <%s>\n", i, array[i], name);
349 if (NULL == name || 0 == *name) {
350 stream->writePackedUInt(0);
351 } else {
commit-bot@chromium.org2cfa3202014-04-19 22:00:40 +0000352 size_t len = strlen(name);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000353 stream->writePackedUInt(len);
354 stream->write(name, len);
355 }
356 }
commit-bot@chromium.orgdcb8e542014-03-05 18:25:20 +0000357
commit-bot@chromium.org06e97522014-03-06 20:53:44 +0000358 SkASSERT(size == (stream->bytesWritten() - start));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000359}
360
commit-bot@chromium.org8f831f22014-04-23 22:35:42 +0000361void SkPicturePlayback::WriteTypefaces(SkWStream* stream, const SkRefCntSet& rec) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000362 int count = rec.count();
reed@google.com82065d62011-02-07 15:30:46 +0000363
commit-bot@chromium.org8f831f22014-04-23 22:35:42 +0000364 SkPicture::WriteTagSize(stream, SK_PICT_TYPEFACE_TAG, count);
reed@google.com82065d62011-02-07 15:30:46 +0000365
reed@android.com8a1c16f2008-12-17 15:59:43 +0000366 SkAutoSTMalloc<16, SkTypeface*> storage(count);
367 SkTypeface** array = (SkTypeface**)storage.get();
mike@reedtribe.orge9e08cc2011-04-29 01:44:52 +0000368 rec.copyToArray((SkRefCnt**)array);
reed@google.com82065d62011-02-07 15:30:46 +0000369
reed@android.com8a1c16f2008-12-17 15:59:43 +0000370 for (int i = 0; i < count; i++) {
371 array[i]->serialize(stream);
372 }
373}
374
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000375void SkPicturePlayback::flattenToBuffer(SkWriteBuffer& buffer) const {
reed@google.comf4cc1872012-07-23 15:04:45 +0000376 int i, n;
reed@google.com82065d62011-02-07 15:30:46 +0000377
reed@google.comf4cc1872012-07-23 15:04:45 +0000378 if ((n = SafeCount(fBitmaps)) > 0) {
commit-bot@chromium.org8f831f22014-04-23 22:35:42 +0000379 SkPicture::WriteTagSize(buffer, SK_PICT_BITMAP_BUFFER_TAG, n);
reed@google.comf4cc1872012-07-23 15:04:45 +0000380 for (i = 0; i < n; i++) {
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000381 buffer.writeBitmap((*fBitmaps)[i]);
reed@google.com67562092012-06-22 15:38:39 +0000382 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000383 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000384
reed@google.comf4cc1872012-07-23 15:04:45 +0000385 if ((n = SafeCount(fPaints)) > 0) {
commit-bot@chromium.org8f831f22014-04-23 22:35:42 +0000386 SkPicture::WriteTagSize(buffer, SK_PICT_PAINT_BUFFER_TAG, n);
reed@google.comf4cc1872012-07-23 15:04:45 +0000387 for (i = 0; i < n; i++) {
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000388 buffer.writePaint((*fPaints)[i]);
reed@google.com67562092012-06-22 15:38:39 +0000389 }
390 }
skia.committer@gmail.coma27096b2012-08-30 14:38:00 +0000391
robertphillipse26e65e2014-06-12 05:51:22 -0700392 if ((n = SafeCount(fPathHeap.get())) > 0) {
393 SkPicture::WriteTagSize(buffer, SK_PICT_PATH_BUFFER_TAG, n);
394 fPathHeap->flatten(buffer);
395 }
reed@google.com67562092012-06-22 15:38:39 +0000396}
reed@google.com82065d62011-02-07 15:30:46 +0000397
scroggo@google.com5a7c6be2012-10-04 21:46:08 +0000398void SkPicturePlayback::serialize(SkWStream* stream,
scroggo@google.com32ef1312013-02-22 22:04:19 +0000399 SkPicture::EncodeBitmap encoder) const {
commit-bot@chromium.org8f831f22014-04-23 22:35:42 +0000400 SkPicture::WriteTagSize(stream, SK_PICT_READER_TAG, fOpData->size());
reed@google.comddf98a82012-07-21 20:31:09 +0000401 stream->write(fOpData->bytes(), fOpData->size());
reed@google.com67562092012-06-22 15:38:39 +0000402
403 if (fPictureCount > 0) {
commit-bot@chromium.org8f831f22014-04-23 22:35:42 +0000404 SkPicture::WriteTagSize(stream, SK_PICT_PICTURE_TAG, fPictureCount);
reed@google.com67562092012-06-22 15:38:39 +0000405 for (int i = 0; i < fPictureCount; i++) {
scroggo@google.comf8d7d272013-02-22 21:38:35 +0000406 fPictureRefs[i]->serialize(stream, encoder);
reed@google.com67562092012-06-22 15:38:39 +0000407 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000408 }
reed@google.com82065d62011-02-07 15:30:46 +0000409
reed@google.com67562092012-06-22 15:38:39 +0000410 // Write some of our data into a writebuffer, and then serialize that
411 // into our stream
412 {
413 SkRefCntSet typefaceSet;
414 SkFactorySet factSet;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000415
commit-bot@chromium.orga2bd2d12014-01-30 22:16:32 +0000416 SkWriteBuffer buffer(SkWriteBuffer::kCrossProcess_Flag);
reed@google.com67562092012-06-22 15:38:39 +0000417 buffer.setTypefaceRecorder(&typefaceSet);
418 buffer.setFactoryRecorder(&factSet);
scroggo@google.com5a7c6be2012-10-04 21:46:08 +0000419 buffer.setBitmapEncoder(encoder);
reed@google.com34342f62012-06-25 14:36:28 +0000420
reed@google.com67562092012-06-22 15:38:39 +0000421 this->flattenToBuffer(buffer);
422
commit-bot@chromium.orgdcb8e542014-03-05 18:25:20 +0000423 // We have to write these two sets into the stream *before* we write
reed@google.com67562092012-06-22 15:38:39 +0000424 // the buffer, since parsing that buffer will require that we already
425 // have these sets available to use.
commit-bot@chromium.org8f831f22014-04-23 22:35:42 +0000426 WriteFactories(stream, factSet);
427 WriteTypefaces(stream, typefaceSet);
reed@google.com67562092012-06-22 15:38:39 +0000428
commit-bot@chromium.org8f831f22014-04-23 22:35:42 +0000429 SkPicture::WriteTagSize(stream, SK_PICT_BUFFER_SIZE_TAG, buffer.bytesWritten());
reed@google.com67562092012-06-22 15:38:39 +0000430 buffer.writeToStream(stream);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000431 }
reed@google.com82065d62011-02-07 15:30:46 +0000432
commit-bot@chromium.org6f4fb0f2014-03-03 19:18:39 +0000433 stream->write32(SK_PICT_EOF_TAG);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000434}
435
commit-bot@chromium.org5e0995e2014-02-07 12:20:04 +0000436void SkPicturePlayback::flatten(SkWriteBuffer& buffer) const {
commit-bot@chromium.org8f831f22014-04-23 22:35:42 +0000437 SkPicture::WriteTagSize(buffer, SK_PICT_READER_TAG, fOpData->size());
commit-bot@chromium.org5e0995e2014-02-07 12:20:04 +0000438 buffer.writeByteArray(fOpData->bytes(), fOpData->size());
439
440 if (fPictureCount > 0) {
commit-bot@chromium.org8f831f22014-04-23 22:35:42 +0000441 SkPicture::WriteTagSize(buffer, SK_PICT_PICTURE_TAG, fPictureCount);
commit-bot@chromium.org5e0995e2014-02-07 12:20:04 +0000442 for (int i = 0; i < fPictureCount; i++) {
443 fPictureRefs[i]->flatten(buffer);
444 }
445 }
446
447 // Write this picture playback's data into a writebuffer
448 this->flattenToBuffer(buffer);
commit-bot@chromium.org6f4fb0f2014-03-03 19:18:39 +0000449 buffer.write32(SK_PICT_EOF_TAG);
commit-bot@chromium.org5e0995e2014-02-07 12:20:04 +0000450}
451
reed@android.com8a1c16f2008-12-17 15:59:43 +0000452///////////////////////////////////////////////////////////////////////////////
453
reed@google.com34342f62012-06-25 14:36:28 +0000454/**
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000455 * Return the corresponding SkReadBuffer flags, given a set of
reed@google.com34342f62012-06-25 14:36:28 +0000456 * SkPictInfo flags.
457 */
458static uint32_t pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags) {
459 static const struct {
460 uint32_t fSrc;
461 uint32_t fDst;
462 } gSD[] = {
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000463 { SkPictInfo::kCrossProcess_Flag, SkReadBuffer::kCrossProcess_Flag },
464 { SkPictInfo::kScalarIsFloat_Flag, SkReadBuffer::kScalarIsFloat_Flag },
465 { SkPictInfo::kPtrIs64Bit_Flag, SkReadBuffer::kPtrIs64Bit_Flag },
reed@google.com34342f62012-06-25 14:36:28 +0000466 };
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000467
reed@google.com34342f62012-06-25 14:36:28 +0000468 uint32_t rbMask = 0;
469 for (size_t i = 0; i < SK_ARRAY_COUNT(gSD); ++i) {
470 if (pictInfoFlags & gSD[i].fSrc) {
471 rbMask |= gSD[i].fDst;
472 }
473 }
474 return rbMask;
475}
476
robertphillipse26e65e2014-06-12 05:51:22 -0700477bool SkPicturePlayback::parseStreamTag(SkStream* stream,
commit-bot@chromium.org0943f5f2014-03-28 18:05:47 +0000478 uint32_t tag,
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000479 uint32_t size,
commit-bot@chromium.org0943f5f2014-03-28 18:05:47 +0000480 SkPicture::InstallPixelRefProc proc) {
reed@google.com67562092012-06-22 15:38:39 +0000481 /*
482 * By the time we encounter BUFFER_SIZE_TAG, we need to have already seen
483 * its dependents: FACTORY_TAG and TYPEFACE_TAG. These two are not required
484 * but if they are present, they need to have been seen before the buffer.
485 *
486 * We assert that if/when we see either of these, that we have not yet seen
487 * the buffer tag, because if we have, then its too-late to deal with the
488 * factories or typefaces.
489 */
scroggo@google.comc4dc8312013-02-22 15:46:44 +0000490 SkDEBUGCODE(bool haveBuffer = false;)
reed@google.com67562092012-06-22 15:38:39 +0000491
492 switch (tag) {
commit-bot@chromium.org6f4fb0f2014-03-03 19:18:39 +0000493 case SK_PICT_READER_TAG: {
scroggo@google.com12705322013-10-01 15:30:46 +0000494 SkAutoMalloc storage(size);
495 if (stream->read(storage.get(), size) != size) {
496 return false;
497 }
reed@google.comddf98a82012-07-21 20:31:09 +0000498 SkASSERT(NULL == fOpData);
scroggo@google.com12705322013-10-01 15:30:46 +0000499 fOpData = SkData::NewFromMalloc(storage.detach(), size);
reed@google.com67562092012-06-22 15:38:39 +0000500 } break;
commit-bot@chromium.org6f4fb0f2014-03-03 19:18:39 +0000501 case SK_PICT_FACTORY_TAG: {
reed@google.com67562092012-06-22 15:38:39 +0000502 SkASSERT(!haveBuffer);
commit-bot@chromium.orgdcb8e542014-03-05 18:25:20 +0000503 // Remove this code when v21 and below are no longer supported. At the
504 // same time add a new 'count' variable and use it rather then reusing 'size'.
505#ifndef DISABLE_V21_COMPATIBILITY_CODE
commit-bot@chromium.org0943f5f2014-03-28 18:05:47 +0000506 if (fInfo.fVersion >= 22) {
commit-bot@chromium.orgdcb8e542014-03-05 18:25:20 +0000507 // in v22 this tag's size represents the size of the chunk in bytes
508 // and the number of factory strings is written out separately
509#endif
510 size = stream->readU32();
511#ifndef DISABLE_V21_COMPATIBILITY_CODE
512 }
513#endif
reed@google.com67562092012-06-22 15:38:39 +0000514 fFactoryPlayback = SkNEW_ARGS(SkFactoryPlayback, (size));
515 for (size_t i = 0; i < size; i++) {
516 SkString str;
scroggo@google.com12705322013-10-01 15:30:46 +0000517 const size_t len = stream->readPackedUInt();
reed@google.com67562092012-06-22 15:38:39 +0000518 str.resize(len);
scroggo@google.com12705322013-10-01 15:30:46 +0000519 if (stream->read(str.writable_str(), len) != len) {
520 return false;
521 }
reed@google.com67562092012-06-22 15:38:39 +0000522 fFactoryPlayback->base()[i] = SkFlattenable::NameToFactory(str.c_str());
523 }
524 } break;
commit-bot@chromium.org6f4fb0f2014-03-03 19:18:39 +0000525 case SK_PICT_TYPEFACE_TAG: {
reed@google.com67562092012-06-22 15:38:39 +0000526 SkASSERT(!haveBuffer);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000527 const int count = SkToInt(size);
528 fTFPlayback.setCount(count);
529 for (int i = 0; i < count; i++) {
reed@google.com73c0abc2013-04-22 13:47:40 +0000530 SkAutoTUnref<SkTypeface> tf(SkTypeface::Deserialize(stream));
531 if (!tf.get()) { // failed to deserialize
532 // fTFPlayback asserts it never has a null, so we plop in
533 // the default here.
534 tf.reset(SkTypeface::RefDefault());
535 }
536 fTFPlayback.set(i, tf);
reed@google.com67562092012-06-22 15:38:39 +0000537 }
538 } break;
commit-bot@chromium.org6f4fb0f2014-03-03 19:18:39 +0000539 case SK_PICT_PICTURE_TAG: {
reed@google.com67562092012-06-22 15:38:39 +0000540 fPictureCount = size;
robertphillips9b14f262014-06-04 05:40:44 -0700541 fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount);
scroggo@google.com12705322013-10-01 15:30:46 +0000542 bool success = true;
543 int i = 0;
544 for ( ; i < fPictureCount; i++) {
scroggo@google.comf1754ec2013-06-28 21:32:00 +0000545 fPictureRefs[i] = SkPicture::CreateFromStream(stream, proc);
scroggo@google.com12705322013-10-01 15:30:46 +0000546 if (NULL == fPictureRefs[i]) {
547 success = false;
548 break;
549 }
550 }
551 if (!success) {
552 // Delete all of the pictures that were already created (up to but excluding i):
553 for (int j = 0; j < i; j++) {
554 fPictureRefs[j]->unref();
555 }
556 // Delete the array
557 SkDELETE_ARRAY(fPictureRefs);
558 fPictureCount = 0;
559 return false;
reed@google.com67562092012-06-22 15:38:39 +0000560 }
561 } break;
commit-bot@chromium.org6f4fb0f2014-03-03 19:18:39 +0000562 case SK_PICT_BUFFER_SIZE_TAG: {
reed@google.com67562092012-06-22 15:38:39 +0000563 SkAutoMalloc storage(size);
scroggo@google.com12705322013-10-01 15:30:46 +0000564 if (stream->read(storage.get(), size) != size) {
565 return false;
566 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000567
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000568 SkReadBuffer buffer(storage.get(), size);
commit-bot@chromium.org0943f5f2014-03-28 18:05:47 +0000569 buffer.setFlags(pictInfoFlagsToReadBufferFlags(fInfo.fFlags));
commit-bot@chromium.org7ed173b2014-05-20 17:31:08 +0000570 buffer.setVersion(fInfo.fVersion);
reed@google.com34342f62012-06-25 14:36:28 +0000571
reed@google.com67562092012-06-22 15:38:39 +0000572 fFactoryPlayback->setupBuffer(buffer);
573 fTFPlayback.setupBuffer(buffer);
scroggo@google.comf8d7d272013-02-22 21:38:35 +0000574 buffer.setBitmapDecoder(proc);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000575
reed@google.com67562092012-06-22 15:38:39 +0000576 while (!buffer.eof()) {
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000577 tag = buffer.readUInt();
578 size = buffer.readUInt();
robertphillipse26e65e2014-06-12 05:51:22 -0700579 if (!this->parseBufferTag(buffer, tag, size)) {
scroggo@google.com12705322013-10-01 15:30:46 +0000580 return false;
581 }
reed@google.com67562092012-06-22 15:38:39 +0000582 }
scroggo@google.comc4dc8312013-02-22 15:46:44 +0000583 SkDEBUGCODE(haveBuffer = true;)
reed@google.com67562092012-06-22 15:38:39 +0000584 } break;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000585 }
scroggo@google.com12705322013-10-01 15:30:46 +0000586 return true; // success
reed@android.com8a1c16f2008-12-17 15:59:43 +0000587}
588
robertphillipse26e65e2014-06-12 05:51:22 -0700589bool SkPicturePlayback::parseBufferTag(SkReadBuffer& buffer,
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000590 uint32_t tag, uint32_t size) {
reed@google.com67562092012-06-22 15:38:39 +0000591 switch (tag) {
commit-bot@chromium.org6f4fb0f2014-03-03 19:18:39 +0000592 case SK_PICT_BITMAP_BUFFER_TAG: {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000593 const int count = SkToInt(size);
reed@google.comf4cc1872012-07-23 15:04:45 +0000594 fBitmaps = SkTRefArray<SkBitmap>::Create(size);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000595 for (int i = 0; i < count; ++i) {
reed@google.comc52295f2012-12-07 15:53:49 +0000596 SkBitmap* bm = &fBitmaps->writableAt(i);
597 buffer.readBitmap(bm);
598 bm->setImmutable();
reed@google.com67562092012-06-22 15:38:39 +0000599 }
600 } break;
commit-bot@chromium.org6f4fb0f2014-03-03 19:18:39 +0000601 case SK_PICT_PAINT_BUFFER_TAG: {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000602 const int count = SkToInt(size);
reed@google.comf4cc1872012-07-23 15:04:45 +0000603 fPaints = SkTRefArray<SkPaint>::Create(size);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000604 for (int i = 0; i < count; ++i) {
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000605 buffer.readPaint(&fPaints->writableAt(i));
reed@google.com67562092012-06-22 15:38:39 +0000606 }
607 } break;
commit-bot@chromium.org6f4fb0f2014-03-03 19:18:39 +0000608 case SK_PICT_PATH_BUFFER_TAG:
robertphillipse26e65e2014-06-12 05:51:22 -0700609 if (size > 0) {
610 fPathHeap.reset(SkNEW_ARGS(SkPathHeap, (buffer)));
611 }
reed@google.com67562092012-06-22 15:38:39 +0000612 break;
commit-bot@chromium.org9e5f85e2014-03-12 14:46:41 +0000613 case SK_PICT_READER_TAG: {
614 SkAutoMalloc storage(size);
615 if (!buffer.readByteArray(storage.get(), size) ||
616 !buffer.validate(NULL == fOpData)) {
617 return false;
618 }
619 SkASSERT(NULL == fOpData);
620 fOpData = SkData::NewFromMalloc(storage.detach(), size);
621 } break;
622 case SK_PICT_PICTURE_TAG: {
623 if (!buffer.validate((0 == fPictureCount) && (NULL == fPictureRefs))) {
624 return false;
625 }
626 fPictureCount = size;
robertphillips9b14f262014-06-04 05:40:44 -0700627 fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount);
commit-bot@chromium.org9e5f85e2014-03-12 14:46:41 +0000628 bool success = true;
629 int i = 0;
630 for ( ; i < fPictureCount; i++) {
631 fPictureRefs[i] = SkPicture::CreateFromBuffer(buffer);
632 if (NULL == fPictureRefs[i]) {
633 success = false;
634 break;
635 }
636 }
637 if (!success) {
638 // Delete all of the pictures that were already created (up to but excluding i):
639 for (int j = 0; j < i; j++) {
640 fPictureRefs[j]->unref();
641 }
642 // Delete the array
643 SkDELETE_ARRAY(fPictureRefs);
644 fPictureCount = 0;
645 return false;
646 }
647 } break;
scroggo@google.com12705322013-10-01 15:30:46 +0000648 default:
649 // The tag was invalid.
650 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000651 }
scroggo@google.com12705322013-10-01 15:30:46 +0000652 return true; // success
reed@android.com8a1c16f2008-12-17 15:59:43 +0000653}
654
robertphillipse26e65e2014-06-12 05:51:22 -0700655SkPicturePlayback* SkPicturePlayback::CreateFromStream(SkStream* stream,
scroggo@google.com12705322013-10-01 15:30:46 +0000656 const SkPictInfo& info,
657 SkPicture::InstallPixelRefProc proc) {
robertphillipse26e65e2014-06-12 05:51:22 -0700658 SkAutoTDelete<SkPicturePlayback> playback(SkNEW_ARGS(SkPicturePlayback, (info)));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000659
robertphillipse26e65e2014-06-12 05:51:22 -0700660 if (!playback->parseStream(stream, proc)) {
scroggo@google.com12705322013-10-01 15:30:46 +0000661 return NULL;
662 }
663 return playback.detach();
664}
665
robertphillipse26e65e2014-06-12 05:51:22 -0700666SkPicturePlayback* SkPicturePlayback::CreateFromBuffer(SkReadBuffer& buffer,
commit-bot@chromium.org0943f5f2014-03-28 18:05:47 +0000667 const SkPictInfo& info) {
robertphillipse26e65e2014-06-12 05:51:22 -0700668 SkAutoTDelete<SkPicturePlayback> playback(SkNEW_ARGS(SkPicturePlayback, (info)));
commit-bot@chromium.org7ed173b2014-05-20 17:31:08 +0000669 buffer.setVersion(info.fVersion);
commit-bot@chromium.org5e0995e2014-02-07 12:20:04 +0000670
robertphillipse26e65e2014-06-12 05:51:22 -0700671 if (!playback->parseBuffer(buffer)) {
commit-bot@chromium.org5e0995e2014-02-07 12:20:04 +0000672 return NULL;
673 }
674 return playback.detach();
675}
676
robertphillipse26e65e2014-06-12 05:51:22 -0700677bool SkPicturePlayback::parseStream(SkStream* stream,
scroggo@google.com12705322013-10-01 15:30:46 +0000678 SkPicture::InstallPixelRefProc proc) {
reed@google.com67562092012-06-22 15:38:39 +0000679 for (;;) {
680 uint32_t tag = stream->readU32();
commit-bot@chromium.org6f4fb0f2014-03-03 19:18:39 +0000681 if (SK_PICT_EOF_TAG == tag) {
reed@google.com67562092012-06-22 15:38:39 +0000682 break;
683 }
reed@google.com82065d62011-02-07 15:30:46 +0000684
reed@google.comed384952012-06-22 13:12:17 +0000685 uint32_t size = stream->readU32();
robertphillipse26e65e2014-06-12 05:51:22 -0700686 if (!this->parseStreamTag(stream, tag, size, proc)) {
scroggo@google.com12705322013-10-01 15:30:46 +0000687 return false; // we're invalid
688 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000689 }
scroggo@google.com12705322013-10-01 15:30:46 +0000690 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000691}
692
robertphillipse26e65e2014-06-12 05:51:22 -0700693bool SkPicturePlayback::parseBuffer(SkReadBuffer& buffer) {
commit-bot@chromium.org5e0995e2014-02-07 12:20:04 +0000694 for (;;) {
695 uint32_t tag = buffer.readUInt();
commit-bot@chromium.org6f4fb0f2014-03-03 19:18:39 +0000696 if (SK_PICT_EOF_TAG == tag) {
commit-bot@chromium.org5e0995e2014-02-07 12:20:04 +0000697 break;
698 }
699
700 uint32_t size = buffer.readUInt();
robertphillipse26e65e2014-06-12 05:51:22 -0700701 if (!this->parseBufferTag(buffer, tag, size)) {
commit-bot@chromium.org5e0995e2014-02-07 12:20:04 +0000702 return false; // we're invalid
703 }
704 }
705 return true;
706}
707
reed@android.com8a1c16f2008-12-17 15:59:43 +0000708///////////////////////////////////////////////////////////////////////////////
709///////////////////////////////////////////////////////////////////////////////
710
reed@android.comae814c82009-02-13 14:56:09 +0000711#ifdef SPEW_CLIP_SKIPPING
712struct SkipClipRec {
713 int fCount;
714 size_t fSize;
reed@google.com82065d62011-02-07 15:30:46 +0000715
reed@android.comae814c82009-02-13 14:56:09 +0000716 SkipClipRec() {
717 fCount = 0;
718 fSize = 0;
719 }
reed@google.com82065d62011-02-07 15:30:46 +0000720
reed@android.comae814c82009-02-13 14:56:09 +0000721 void recordSkip(size_t bytes) {
722 fCount += 1;
723 fSize += bytes;
724 }
725};
726#endif
727
robertphillips@google.com3f713722013-01-17 14:39:20 +0000728#ifdef SK_DEVELOPER
robertphillips@google.com6d9c92b2013-05-23 13:21:18 +0000729bool SkPicturePlayback::preDraw(int opIndex, int type) {
730 return false;
robertphillips@google.com6f6dfb42012-11-13 18:28:06 +0000731}
732
robertphillips@google.com6d9c92b2013-05-23 13:21:18 +0000733void SkPicturePlayback::postDraw(int opIndex) {
robertphillips@google.com6f6dfb42012-11-13 18:28:06 +0000734}
735#endif
736
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000737/*
robertphillips@google.come4ce5b82013-02-15 17:19:15 +0000738 * Read the next op code and chunk size from 'reader'. The returned size
skia.committer@gmail.comce8343d2013-02-16 07:01:31 +0000739 * is the entire size of the chunk (including the opcode). Thus, the
robertphillips@google.come4ce5b82013-02-15 17:19:15 +0000740 * offset just prior to calling read_op_and_size + 'size' is the offset
skia.committer@gmail.comce8343d2013-02-16 07:01:31 +0000741 * to the next chunk's op code. This also means that the size of a chunk
robertphillips@google.come4ce5b82013-02-15 17:19:15 +0000742 * with no arguments (just an opcode) will be 4.
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000743 */
744static DrawType read_op_and_size(SkReader32* reader, uint32_t* size) {
745 uint32_t temp = reader->readInt();
746 uint32_t op;
747 if (((uint8_t) temp) == temp) {
748 // old skp file - no size information
749 op = temp;
750 *size = 0;
751 } else {
752 UNPACK_8_24(temp, op, *size);
753 if (MASK_24 == *size) {
754 *size = reader->readInt();
755 }
756 }
757 return (DrawType) op;
758}
759
commit-bot@chromium.org70512af2014-03-18 17:45:32 +0000760uint32_t SkPicturePlayback::CachedOperationList::offset(int index) const {
761 SkASSERT(index < fOps.count());
762 return ((SkPictureStateTree::Draw*)fOps[index])->fOffset;
763}
764
765const SkMatrix& SkPicturePlayback::CachedOperationList::matrix(int index) const {
766 SkASSERT(index < fOps.count());
767 return *((SkPictureStateTree::Draw*)fOps[index])->fMatrix;
768}
769
770const SkPicture::OperationList& SkPicturePlayback::getActiveOps(const SkIRect& query) {
771 if (NULL == fStateTree || NULL == fBoundingHierarchy) {
772 return SkPicture::OperationList::InvalidList();
773 }
774
775 if (NULL == fCachedActiveOps) {
776 fCachedActiveOps = SkNEW(CachedOperationList);
777 }
778
779 if (query == fCachedActiveOps->fCacheQueryRect) {
780 return *fCachedActiveOps;
781 }
782
783 fCachedActiveOps->fOps.rewind();
784
785 fBoundingHierarchy->search(query, &(fCachedActiveOps->fOps));
786 if (0 != fCachedActiveOps->fOps.count()) {
787 SkTQSort<SkPictureStateTree::Draw>(
788 reinterpret_cast<SkPictureStateTree::Draw**>(fCachedActiveOps->fOps.begin()),
789 reinterpret_cast<SkPictureStateTree::Draw**>(fCachedActiveOps->fOps.end()-1));
790 }
791
792 fCachedActiveOps->fCacheQueryRect = query;
793 return *fCachedActiveOps;
794}
795
commit-bot@chromium.org75cf29b2014-03-24 19:40:49 +0000796class SkAutoResetOpID {
797public:
798 SkAutoResetOpID(SkPicturePlayback* playback) : fPlayback(playback) { }
799 ~SkAutoResetOpID() {
800 if (NULL != fPlayback) {
801 fPlayback->resetOpID();
802 }
803 }
804
805private:
806 SkPicturePlayback* fPlayback;
807};
808
robertphillips@google.combeb1af22014-05-07 21:31:09 +0000809// TODO: Replace with hash or pass in "lastLookedUp" hint
skia.committer@gmail.comb2c82c92014-05-08 03:05:29 +0000810SkPicturePlayback::PlaybackReplacements::ReplacementInfo*
robertphillips@google.combeb1af22014-05-07 21:31:09 +0000811SkPicturePlayback::PlaybackReplacements::lookupByStart(size_t start) {
812 SkDEBUGCODE(this->validate());
813 for (int i = 0; i < fReplacements.count(); ++i) {
814 if (start == fReplacements[i].fStart) {
815 return &fReplacements[i];
816 } else if (start < fReplacements[i].fStart) {
817 return NULL; // the ranges are monotonically increasing and non-overlapping
818 }
819 }
820
821 return NULL;
822}
823
reed@google.com74babdf2013-05-20 17:02:41 +0000824void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback) {
commit-bot@chromium.org75cf29b2014-03-24 19:40:49 +0000825 SkAutoResetOpID aroi(this);
826 SkASSERT(0 == fCurOffset);
827
reed@android.com8a1c16f2008-12-17 15:59:43 +0000828#ifdef ENABLE_TIME_DRAW
829 SkAutoTime at("SkPicture::draw", 50);
830#endif
reed@google.com82065d62011-02-07 15:30:46 +0000831
reed@android.comae814c82009-02-13 14:56:09 +0000832#ifdef SPEW_CLIP_SKIPPING
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000833 SkipClipRec skipRect, skipRRect, skipRegion, skipPath, skipCull;
834 int opCount = 0;
reed@android.comae814c82009-02-13 14:56:09 +0000835#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000836
djsollen@google.com56c69772011-11-08 19:00:26 +0000837#ifdef SK_BUILD_FOR_ANDROID
djsollen@google.comf5dbe2f2011-04-15 13:41:26 +0000838 SkAutoMutexAcquire autoMutex(fDrawMutex);
839#endif
840
robertphillips@google.com5f971142012-12-07 20:48:56 +0000841 // kDrawComplete will be the signal that we have reached the end of
842 // the command stream
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000843 static const uint32_t kDrawComplete = SK_MaxU32;
robertphillips@google.com5f971142012-12-07 20:48:56 +0000844
reed@google.comddf98a82012-07-21 20:31:09 +0000845 SkReader32 reader(fOpData->bytes(), fOpData->size());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000846 TextContainer text;
commit-bot@chromium.org70512af2014-03-18 17:45:32 +0000847 const SkTDArray<void*>* activeOps = NULL;
rileya@google.com8515e792012-09-13 21:41:51 +0000848
robertphillips@google.combeb1af22014-05-07 21:31:09 +0000849 // When draw limits are enabled (i.e., 0 != fStart || 0 != fStop) the state
850 // tree isn't used to pick and choose the draw operations
851 if (0 == fStart && 0 == fStop) {
852 if (fUseBBH && NULL != fStateTree && NULL != fBoundingHierarchy) {
853 SkRect clipBounds;
854 if (canvas.getClipBounds(&clipBounds)) {
855 SkIRect query;
856 clipBounds.roundOut(&query);
commit-bot@chromium.org70512af2014-03-18 17:45:32 +0000857
robertphillips@google.combeb1af22014-05-07 21:31:09 +0000858 const SkPicture::OperationList& activeOpsList = this->getActiveOps(query);
859 if (activeOpsList.valid()) {
860 if (0 == activeOpsList.numOps()) {
861 return; // nothing to draw
862 }
863
864 // Since the opList is valid we know it is our derived class
865 activeOps = &((const CachedOperationList&)activeOpsList).fOps;
commit-bot@chromium.org70512af2014-03-18 17:45:32 +0000866 }
rileya@google.com1c6307e2012-09-14 15:52:47 +0000867 }
rileya@google.com8515e792012-09-13 21:41:51 +0000868 }
869 }
870
commit-bot@chromium.org70512af2014-03-18 17:45:32 +0000871 SkPictureStateTree::Iterator it = (NULL == activeOps) ?
rileya@google.com8515e792012-09-13 21:41:51 +0000872 SkPictureStateTree::Iterator() :
commit-bot@chromium.org70512af2014-03-18 17:45:32 +0000873 fStateTree->getIterator(*activeOps, &canvas);
rileya@google.com8515e792012-09-13 21:41:51 +0000874
robertphillips@google.combeb1af22014-05-07 21:31:09 +0000875 if (0 != fStart || 0 != fStop) {
876 reader.setOffset(fStart);
877 uint32_t size;
878 SkDEBUGCODE(DrawType op =) read_op_and_size(&reader, &size);
879 SkASSERT(SAVE_LAYER == op);
880 reader.setOffset(fStart+size);
881 }
882
rileya@google.com8515e792012-09-13 21:41:51 +0000883 if (it.isValid()) {
commit-bot@chromium.orga31eacb2014-04-28 20:17:48 +0000884 uint32_t skipTo = it.nextDraw();
robertphillips@google.com5f971142012-12-07 20:48:56 +0000885 if (kDrawComplete == skipTo) {
rileya@google.com1c6307e2012-09-14 15:52:47 +0000886 return;
887 }
robertphillips@google.com5f971142012-12-07 20:48:56 +0000888 reader.setOffset(skipTo);
rileya@google.com8515e792012-09-13 21:41:51 +0000889 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000890
reed@google.comb4c28192012-09-05 23:14:07 +0000891 // Record this, so we can concat w/ it if we encounter a setMatrix()
892 SkMatrix initialMatrix = canvas.getTotalMatrix();
commit-bot@chromium.org82165062014-05-19 12:26:58 +0000893
894 SkAutoCanvasRestore acr(&canvas, false);
reed@google.comb4c28192012-09-05 23:14:07 +0000895
djsollen@google.comd9b0f482013-02-01 16:18:09 +0000896#ifdef SK_BUILD_FOR_ANDROID
897 fAbortCurrentPlayback = false;
898#endif
899
robertphillips@google.com6d9c92b2013-05-23 13:21:18 +0000900#ifdef SK_DEVELOPER
901 int opIndex = -1;
902#endif
903
reed@google.comddf98a82012-07-21 20:31:09 +0000904 while (!reader.eof()) {
reed@google.com74babdf2013-05-20 17:02:41 +0000905 if (callback && callback->abortDrawing()) {
reed@google.com74babdf2013-05-20 17:02:41 +0000906 return;
907 }
djsollen@google.comd9b0f482013-02-01 16:18:09 +0000908#ifdef SK_BUILD_FOR_ANDROID
909 if (fAbortCurrentPlayback) {
910 return;
911 }
912#endif
robertphillips@google.combeb1af22014-05-07 21:31:09 +0000913 if (0 != fStart || 0 != fStop) {
914 size_t offset = reader.offset() ;
915 if (offset >= fStop) {
916 uint32_t size;
917 SkDEBUGCODE(DrawType op =) read_op_and_size(&reader, &size);
918 SkASSERT(RESTORE == op);
919 return;
920 }
921 }
922
923 if (NULL != fReplacements) {
924 // Potentially replace a block of operations with a single drawBitmap call
skia.committer@gmail.comb2c82c92014-05-08 03:05:29 +0000925 SkPicturePlayback::PlaybackReplacements::ReplacementInfo* temp =
robertphillips@google.combeb1af22014-05-07 21:31:09 +0000926 fReplacements->lookupByStart(reader.offset());
927 if (NULL != temp) {
928 SkASSERT(NULL != temp->fBM);
929 SkASSERT(NULL != temp->fPaint);
commit-bot@chromium.orgf97d65d2014-05-08 23:24:05 +0000930 canvas.save();
931 canvas.setMatrix(initialMatrix);
robertphillipse462f2b2014-06-29 17:16:27 -0700932 canvas.drawBitmap(*temp->fBM, temp->fPos.fX, temp->fPos.fY, temp->fPaint);
commit-bot@chromium.orgf97d65d2014-05-08 23:24:05 +0000933 canvas.restore();
robertphillips@google.combeb1af22014-05-07 21:31:09 +0000934
935 if (it.isValid()) {
936 // This save is needed since the BBH will automatically issue
937 // a restore to balanced the saveLayer we're skipping
938 canvas.save();
robertphillips@google.combeb1af22014-05-07 21:31:09 +0000939
940 // At this point we know that the PictureStateTree was aiming
941 // for some draw op within temp's saveLayer (although potentially
942 // in a separate saveLayer nested inside it).
943 // We need to skip all the operations inside temp's range
skia.committer@gmail.comb2c82c92014-05-08 03:05:29 +0000944 // along with all the associated state changes but update
robertphillips@google.combeb1af22014-05-07 21:31:09 +0000945 // the state tree to the first operation outside temp's range.
robertphillips@google.combeb1af22014-05-07 21:31:09 +0000946
commit-bot@chromium.orgf97d65d2014-05-08 23:24:05 +0000947 uint32_t skipTo;
948 do {
949 skipTo = it.nextDraw();
950 if (kDrawComplete == skipTo) {
951 break;
952 }
robertphillips@google.combeb1af22014-05-07 21:31:09 +0000953
commit-bot@chromium.orgf97d65d2014-05-08 23:24:05 +0000954 if (skipTo <= temp->fStop) {
955 reader.setOffset(skipTo);
956 uint32_t size;
957 DrawType op = read_op_and_size(&reader, &size);
958 // Since we are relying on the normal SkPictureStateTree
959 // playback we need to convert any nested saveLayer calls
960 // it may issue into saves (so that all its internal
961 // restores will be balanced).
962 if (SAVE_LAYER == op) {
963 canvas.save();
964 }
965 }
966 } while (skipTo <= temp->fStop);
967
968 if (kDrawComplete == skipTo) {
robertphillips@google.combeb1af22014-05-07 21:31:09 +0000969 break;
970 }
971
robertphillips@google.combeb1af22014-05-07 21:31:09 +0000972 reader.setOffset(skipTo);
973 } else {
974 reader.setOffset(temp->fStop);
975 uint32_t size;
976 SkDEBUGCODE(DrawType op =) read_op_and_size(&reader, &size);
977 SkASSERT(RESTORE == op);
978 }
979 continue;
980 }
981 }
djsollen@google.comd9b0f482013-02-01 16:18:09 +0000982
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000983#ifdef SPEW_CLIP_SKIPPING
984 opCount++;
985#endif
986
commit-bot@chromium.org75cf29b2014-03-24 19:40:49 +0000987 fCurOffset = reader.offset();
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000988 uint32_t size;
989 DrawType op = read_op_and_size(&reader, &size);
commit-bot@chromium.org4b32bd52013-03-15 15:06:03 +0000990 size_t skipTo = 0;
robertphillips@google.com6d9c92b2013-05-23 13:21:18 +0000991 if (NOOP == op) {
robertphillips@google.come4ce5b82013-02-15 17:19:15 +0000992 // NOOPs are to be ignored - do not propagate them any further
commit-bot@chromium.org75cf29b2014-03-24 19:40:49 +0000993 skipTo = fCurOffset + size;
robertphillips@google.com6d9c92b2013-05-23 13:21:18 +0000994#ifdef SK_DEVELOPER
995 } else {
996 opIndex++;
997 if (this->preDraw(opIndex, op)) {
commit-bot@chromium.org75cf29b2014-03-24 19:40:49 +0000998 skipTo = fCurOffset + size;
robertphillips@google.com6d9c92b2013-05-23 13:21:18 +0000999 }
1000#endif
robertphillips@google.come4ce5b82013-02-15 17:19:15 +00001001 }
1002
robertphillips@google.com5f971142012-12-07 20:48:56 +00001003 if (0 != skipTo) {
commit-bot@chromium.org4b32bd52013-03-15 15:06:03 +00001004 if (it.isValid()) {
1005 // If using a bounding box hierarchy, advance the state tree
1006 // iterator until at or after skipTo
1007 uint32_t adjustedSkipTo;
1008 do {
commit-bot@chromium.orga31eacb2014-04-28 20:17:48 +00001009 adjustedSkipTo = it.nextDraw();
commit-bot@chromium.org4b32bd52013-03-15 15:06:03 +00001010 } while (adjustedSkipTo < skipTo);
1011 skipTo = adjustedSkipTo;
1012 }
robertphillips@google.com5f971142012-12-07 20:48:56 +00001013 if (kDrawComplete == skipTo) {
1014 break;
1015 }
1016 reader.setOffset(skipTo);
1017 continue;
1018 }
commit-bot@chromium.org4b32bd52013-03-15 15:06:03 +00001019
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +00001020 switch (op) {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001021 case CLIP_PATH: {
reed@google.comddf98a82012-07-21 20:31:09 +00001022 const SkPath& path = getPath(reader);
1023 uint32_t packed = reader.readInt();
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +00001024 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
reed@google.com83ab4952011-11-11 21:34:54 +00001025 bool doAA = ClipParams_unpackDoAA(packed);
reed@google.comddf98a82012-07-21 20:31:09 +00001026 size_t offsetToRestore = reader.readInt();
junov@chromium.org9fa4d0c2012-07-09 20:53:37 +00001027 SkASSERT(!offsetToRestore || \
reed@google.comddf98a82012-07-21 20:31:09 +00001028 offsetToRestore >= reader.offset());
robertphillips@google.com8f90a892014-02-28 18:19:39 +00001029 canvas.clipPath(path, regionOp, doAA);
1030 if (canvas.isClipEmpty() && offsetToRestore) {
reed@android.comae814c82009-02-13 14:56:09 +00001031#ifdef SPEW_CLIP_SKIPPING
reed@google.comddf98a82012-07-21 20:31:09 +00001032 skipPath.recordSkip(offsetToRestore - reader.offset());
reed@android.comae814c82009-02-13 14:56:09 +00001033#endif
reed@google.comddf98a82012-07-21 20:31:09 +00001034 reader.setOffset(offsetToRestore);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001035 }
1036 } break;
1037 case CLIP_REGION: {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +00001038 SkRegion region;
1039 this->getRegion(reader, &region);
reed@google.comddf98a82012-07-21 20:31:09 +00001040 uint32_t packed = reader.readInt();
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +00001041 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
reed@google.comddf98a82012-07-21 20:31:09 +00001042 size_t offsetToRestore = reader.readInt();
junov@chromium.org9fa4d0c2012-07-09 20:53:37 +00001043 SkASSERT(!offsetToRestore || \
reed@google.comddf98a82012-07-21 20:31:09 +00001044 offsetToRestore >= reader.offset());
robertphillips@google.com8f90a892014-02-28 18:19:39 +00001045 canvas.clipRegion(region, regionOp);
1046 if (canvas.isClipEmpty() && offsetToRestore) {
reed@android.comae814c82009-02-13 14:56:09 +00001047#ifdef SPEW_CLIP_SKIPPING
reed@google.comddf98a82012-07-21 20:31:09 +00001048 skipRegion.recordSkip(offsetToRestore - reader.offset());
reed@android.comae814c82009-02-13 14:56:09 +00001049#endif
reed@google.comddf98a82012-07-21 20:31:09 +00001050 reader.setOffset(offsetToRestore);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001051 }
1052 } break;
1053 case CLIP_RECT: {
reed@google.comddf98a82012-07-21 20:31:09 +00001054 const SkRect& rect = reader.skipT<SkRect>();
1055 uint32_t packed = reader.readInt();
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +00001056 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
reed@google.com83ab4952011-11-11 21:34:54 +00001057 bool doAA = ClipParams_unpackDoAA(packed);
reed@google.comddf98a82012-07-21 20:31:09 +00001058 size_t offsetToRestore = reader.readInt();
junov@chromium.org9fa4d0c2012-07-09 20:53:37 +00001059 SkASSERT(!offsetToRestore || \
reed@google.com4ed0fb72012-12-12 20:48:18 +00001060 offsetToRestore >= reader.offset());
robertphillips@google.com8f90a892014-02-28 18:19:39 +00001061 canvas.clipRect(rect, regionOp, doAA);
1062 if (canvas.isClipEmpty() && offsetToRestore) {
reed@android.comae814c82009-02-13 14:56:09 +00001063#ifdef SPEW_CLIP_SKIPPING
reed@google.comddf98a82012-07-21 20:31:09 +00001064 skipRect.recordSkip(offsetToRestore - reader.offset());
reed@android.comae814c82009-02-13 14:56:09 +00001065#endif
reed@google.comddf98a82012-07-21 20:31:09 +00001066 reader.setOffset(offsetToRestore);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001067 }
1068 } break;
reed@google.com4ed0fb72012-12-12 20:48:18 +00001069 case CLIP_RRECT: {
1070 SkRRect rrect;
1071 reader.readRRect(&rrect);
1072 uint32_t packed = reader.readInt();
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +00001073 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
reed@google.com4ed0fb72012-12-12 20:48:18 +00001074 bool doAA = ClipParams_unpackDoAA(packed);
1075 size_t offsetToRestore = reader.readInt();
robertphillips@google.combeb1af22014-05-07 21:31:09 +00001076 SkASSERT(!offsetToRestore || offsetToRestore >= reader.offset());
robertphillips@google.com8f90a892014-02-28 18:19:39 +00001077 canvas.clipRRect(rrect, regionOp, doAA);
1078 if (canvas.isClipEmpty() && offsetToRestore) {
reed@google.com4ed0fb72012-12-12 20:48:18 +00001079#ifdef SPEW_CLIP_SKIPPING
1080 skipRRect.recordSkip(offsetToRestore - reader.offset());
1081#endif
1082 reader.setOffset(offsetToRestore);
1083 }
1084 } break;
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +00001085 case PUSH_CULL: {
1086 const SkRect& cullRect = reader.skipT<SkRect>();
1087 size_t offsetToRestore = reader.readInt();
1088 if (offsetToRestore && canvas.quickReject(cullRect)) {
1089#ifdef SPEW_CLIP_SKIPPING
1090 skipCull.recordSkip(offsetToRestore - reader.offset());
1091#endif
1092 reader.setOffset(offsetToRestore);
1093 } else {
1094 canvas.pushCull(cullRect);
1095 }
1096 } break;
1097 case POP_CULL:
1098 canvas.popCull();
1099 break;
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +00001100 case CONCAT: {
1101 SkMatrix matrix;
1102 this->getMatrix(reader, &matrix);
1103 canvas.concat(matrix);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001104 break;
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +00001105 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001106 case DRAW_BITMAP: {
commit-bot@chromium.orgd7e0fbe2014-03-10 16:41:00 +00001107 const SkPaint* paint = this->getPaint(reader);
1108 const SkBitmap& bitmap = this->getBitmap(reader);
reed@google.comddf98a82012-07-21 20:31:09 +00001109 const SkPoint& loc = reader.skipT<SkPoint>();
reed@google.coma5adf532011-09-07 13:52:17 +00001110 canvas.drawBitmap(bitmap, loc.fX, loc.fY, paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001111 } break;
reed@google.com71121732012-09-18 15:14:33 +00001112 case DRAW_BITMAP_RECT_TO_RECT: {
commit-bot@chromium.orgd7e0fbe2014-03-10 16:41:00 +00001113 const SkPaint* paint = this->getPaint(reader);
1114 const SkBitmap& bitmap = this->getBitmap(reader);
reed@google.com71121732012-09-18 15:14:33 +00001115 const SkRect* src = this->getRectPtr(reader); // may be null
reed@google.comddf98a82012-07-21 20:31:09 +00001116 const SkRect& dst = reader.skipT<SkRect>(); // required
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +00001117 SkCanvas::DrawBitmapRectFlags flags;
robertphillips@google.com11e05552013-12-03 19:46:58 +00001118 flags = (SkCanvas::DrawBitmapRectFlags) reader.readInt();
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +00001119 canvas.drawBitmapRectToRect(bitmap, src, dst, paint, flags);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001120 } break;
1121 case DRAW_BITMAP_MATRIX: {
commit-bot@chromium.orgd7e0fbe2014-03-10 16:41:00 +00001122 const SkPaint* paint = this->getPaint(reader);
1123 const SkBitmap& bitmap = this->getBitmap(reader);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +00001124 SkMatrix matrix;
1125 this->getMatrix(reader, &matrix);
1126 canvas.drawBitmapMatrix(bitmap, matrix, paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001127 } break;
reed@google.comf0b5e112011-09-07 11:57:34 +00001128 case DRAW_BITMAP_NINE: {
commit-bot@chromium.orgd7e0fbe2014-03-10 16:41:00 +00001129 const SkPaint* paint = this->getPaint(reader);
1130 const SkBitmap& bitmap = this->getBitmap(reader);
reed@google.comddf98a82012-07-21 20:31:09 +00001131 const SkIRect& src = reader.skipT<SkIRect>();
1132 const SkRect& dst = reader.skipT<SkRect>();
reed@google.coma5adf532011-09-07 13:52:17 +00001133 canvas.drawBitmapNine(bitmap, src, dst, paint);
reed@google.comf0b5e112011-09-07 11:57:34 +00001134 } break;
reed@google.com2a981812011-04-14 18:59:28 +00001135 case DRAW_CLEAR:
reed@google.comddf98a82012-07-21 20:31:09 +00001136 canvas.clear(reader.readInt());
reed@google.com2a981812011-04-14 18:59:28 +00001137 break;
reed@android.comcb608442009-12-04 21:32:27 +00001138 case DRAW_DATA: {
reed@google.comddf98a82012-07-21 20:31:09 +00001139 size_t length = reader.readInt();
1140 canvas.drawData(reader.skip(length), length);
reed@android.comcb608442009-12-04 21:32:27 +00001141 // skip handles padding the read out to a multiple of 4
1142 } break;
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +00001143 case DRAW_DRRECT: {
commit-bot@chromium.orgd7e0fbe2014-03-10 16:41:00 +00001144 const SkPaint& paint = *this->getPaint(reader);
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +00001145 SkRRect outer, inner;
1146 reader.readRRect(&outer);
1147 reader.readRRect(&inner);
1148 canvas.drawDRRect(outer, inner, paint);
1149 } break;
robertphillips@google.com0a4805e2013-05-29 13:24:23 +00001150 case BEGIN_COMMENT_GROUP: {
1151 const char* desc = reader.readString();
1152 canvas.beginCommentGroup(desc);
1153 } break;
1154 case COMMENT: {
1155 const char* kywd = reader.readString();
1156 const char* value = reader.readString();
1157 canvas.addComment(kywd, value);
1158 } break;
1159 case END_COMMENT_GROUP: {
1160 canvas.endCommentGroup();
1161 } break;
reed@google.com4ed0fb72012-12-12 20:48:18 +00001162 case DRAW_OVAL: {
commit-bot@chromium.orgd7e0fbe2014-03-10 16:41:00 +00001163 const SkPaint& paint = *this->getPaint(reader);
reed@google.com4ed0fb72012-12-12 20:48:18 +00001164 canvas.drawOval(reader.skipT<SkRect>(), paint);
1165 } break;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001166 case DRAW_PAINT:
commit-bot@chromium.orgd7e0fbe2014-03-10 16:41:00 +00001167 canvas.drawPaint(*this->getPaint(reader));
reed@android.com8a1c16f2008-12-17 15:59:43 +00001168 break;
1169 case DRAW_PATH: {
commit-bot@chromium.orgd7e0fbe2014-03-10 16:41:00 +00001170 const SkPaint& paint = *this->getPaint(reader);
reed@google.comddf98a82012-07-21 20:31:09 +00001171 canvas.drawPath(getPath(reader), paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001172 } break;
1173 case DRAW_PICTURE:
commit-bot@chromium.orgd7e0fbe2014-03-10 16:41:00 +00001174 canvas.drawPicture(this->getPicture(reader));
reed@android.com8a1c16f2008-12-17 15:59:43 +00001175 break;
1176 case DRAW_POINTS: {
commit-bot@chromium.orgd7e0fbe2014-03-10 16:41:00 +00001177 const SkPaint& paint = *this->getPaint(reader);
reed@google.comddf98a82012-07-21 20:31:09 +00001178 SkCanvas::PointMode mode = (SkCanvas::PointMode)reader.readInt();
1179 size_t count = reader.readInt();
1180 const SkPoint* pts = (const SkPoint*)reader.skip(sizeof(SkPoint) * count);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001181 canvas.drawPoints(mode, count, pts, paint);
1182 } break;
1183 case DRAW_POS_TEXT: {
commit-bot@chromium.orgd7e0fbe2014-03-10 16:41:00 +00001184 const SkPaint& paint = *this->getPaint(reader);
reed@google.comddf98a82012-07-21 20:31:09 +00001185 getText(reader, &text);
1186 size_t points = reader.readInt();
1187 const SkPoint* pos = (const SkPoint*)reader.skip(points * sizeof(SkPoint));
reed@android.com8a1c16f2008-12-17 15:59:43 +00001188 canvas.drawPosText(text.text(), text.length(), pos, paint);
1189 } break;
reed@google.com9efd9a02012-01-30 15:41:43 +00001190 case DRAW_POS_TEXT_TOP_BOTTOM: {
commit-bot@chromium.orgd7e0fbe2014-03-10 16:41:00 +00001191 const SkPaint& paint = *this->getPaint(reader);
reed@google.comddf98a82012-07-21 20:31:09 +00001192 getText(reader, &text);
1193 size_t points = reader.readInt();
1194 const SkPoint* pos = (const SkPoint*)reader.skip(points * sizeof(SkPoint));
1195 const SkScalar top = reader.readScalar();
1196 const SkScalar bottom = reader.readScalar();
reed@google.com3b3e8952012-08-16 20:53:31 +00001197 if (!canvas.quickRejectY(top, bottom)) {
reed@google.com9efd9a02012-01-30 15:41:43 +00001198 canvas.drawPosText(text.text(), text.length(), pos, paint);
1199 }
1200 } break;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001201 case DRAW_POS_TEXT_H: {
commit-bot@chromium.orgd7e0fbe2014-03-10 16:41:00 +00001202 const SkPaint& paint = *this->getPaint(reader);
reed@google.comddf98a82012-07-21 20:31:09 +00001203 getText(reader, &text);
1204 size_t xCount = reader.readInt();
1205 const SkScalar constY = reader.readScalar();
1206 const SkScalar* xpos = (const SkScalar*)reader.skip(xCount * sizeof(SkScalar));
reed@android.com8a1c16f2008-12-17 15:59:43 +00001207 canvas.drawPosTextH(text.text(), text.length(), xpos, constY,
1208 paint);
1209 } break;
1210 case DRAW_POS_TEXT_H_TOP_BOTTOM: {
commit-bot@chromium.orgd7e0fbe2014-03-10 16:41:00 +00001211 const SkPaint& paint = *this->getPaint(reader);
reed@google.comddf98a82012-07-21 20:31:09 +00001212 getText(reader, &text);
1213 size_t xCount = reader.readInt();
1214 const SkScalar* xpos = (const SkScalar*)reader.skip((3 + xCount) * sizeof(SkScalar));
reed@android.com8a1c16f2008-12-17 15:59:43 +00001215 const SkScalar top = *xpos++;
1216 const SkScalar bottom = *xpos++;
1217 const SkScalar constY = *xpos++;
reed@google.com3b3e8952012-08-16 20:53:31 +00001218 if (!canvas.quickRejectY(top, bottom)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001219 canvas.drawPosTextH(text.text(), text.length(), xpos,
1220 constY, paint);
1221 }
1222 } break;
1223 case DRAW_RECT: {
commit-bot@chromium.orgd7e0fbe2014-03-10 16:41:00 +00001224 const SkPaint& paint = *this->getPaint(reader);
reed@google.comddf98a82012-07-21 20:31:09 +00001225 canvas.drawRect(reader.skipT<SkRect>(), paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001226 } break;
reed@google.com4ed0fb72012-12-12 20:48:18 +00001227 case DRAW_RRECT: {
commit-bot@chromium.orgd7e0fbe2014-03-10 16:41:00 +00001228 const SkPaint& paint = *this->getPaint(reader);
reed@google.com4ed0fb72012-12-12 20:48:18 +00001229 SkRRect rrect;
commit-bot@chromium.org4faa8692013-11-05 15:46:56 +00001230 reader.readRRect(&rrect);
1231 canvas.drawRRect(rrect, paint);
reed@google.com4ed0fb72012-12-12 20:48:18 +00001232 } break;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001233 case DRAW_SPRITE: {
commit-bot@chromium.orgd7e0fbe2014-03-10 16:41:00 +00001234 const SkPaint* paint = this->getPaint(reader);
1235 const SkBitmap& bitmap = this->getBitmap(reader);
reed@google.comddf98a82012-07-21 20:31:09 +00001236 int left = reader.readInt();
1237 int top = reader.readInt();
reed@google.com82065d62011-02-07 15:30:46 +00001238 canvas.drawSprite(bitmap, left, top, paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001239 } break;
1240 case DRAW_TEXT: {
commit-bot@chromium.orgd7e0fbe2014-03-10 16:41:00 +00001241 const SkPaint& paint = *this->getPaint(reader);
1242 this->getText(reader, &text);
reed@google.comddf98a82012-07-21 20:31:09 +00001243 SkScalar x = reader.readScalar();
1244 SkScalar y = reader.readScalar();
reed@android.com8a1c16f2008-12-17 15:59:43 +00001245 canvas.drawText(text.text(), text.length(), x, y, paint);
1246 } break;
1247 case DRAW_TEXT_TOP_BOTTOM: {
commit-bot@chromium.orgd7e0fbe2014-03-10 16:41:00 +00001248 const SkPaint& paint = *this->getPaint(reader);
1249 this->getText(reader, &text);
reed@google.comddf98a82012-07-21 20:31:09 +00001250 const SkScalar* ptr = (const SkScalar*)reader.skip(4 * sizeof(SkScalar));
reed@android.com8a1c16f2008-12-17 15:59:43 +00001251 // ptr[0] == x
1252 // ptr[1] == y
1253 // ptr[2] == top
1254 // ptr[3] == bottom
reed@google.com3b3e8952012-08-16 20:53:31 +00001255 if (!canvas.quickRejectY(ptr[2], ptr[3])) {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001256 canvas.drawText(text.text(), text.length(), ptr[0], ptr[1],
1257 paint);
1258 }
1259 } break;
1260 case DRAW_TEXT_ON_PATH: {
commit-bot@chromium.orgd7e0fbe2014-03-10 16:41:00 +00001261 const SkPaint& paint = *this->getPaint(reader);
reed@google.comddf98a82012-07-21 20:31:09 +00001262 getText(reader, &text);
commit-bot@chromium.orgd7e0fbe2014-03-10 16:41:00 +00001263 const SkPath& path = this->getPath(reader);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +00001264 SkMatrix matrix;
1265 this->getMatrix(reader, &matrix);
1266 canvas.drawTextOnPath(text.text(), text.length(), path, &matrix, paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001267 } break;
1268 case DRAW_VERTICES: {
reed@google.com85e143c2013-12-30 15:51:25 +00001269 SkAutoTUnref<SkXfermode> xfer;
commit-bot@chromium.orgd7e0fbe2014-03-10 16:41:00 +00001270 const SkPaint& paint = *this->getPaint(reader);
reed@google.comddf98a82012-07-21 20:31:09 +00001271 DrawVertexFlags flags = (DrawVertexFlags)reader.readInt();
1272 SkCanvas::VertexMode vmode = (SkCanvas::VertexMode)reader.readInt();
1273 int vCount = reader.readInt();
1274 const SkPoint* verts = (const SkPoint*)reader.skip(
reed@android.com8a1c16f2008-12-17 15:59:43 +00001275 vCount * sizeof(SkPoint));
1276 const SkPoint* texs = NULL;
1277 const SkColor* colors = NULL;
1278 const uint16_t* indices = NULL;
1279 int iCount = 0;
1280 if (flags & DRAW_VERTICES_HAS_TEXS) {
reed@google.comddf98a82012-07-21 20:31:09 +00001281 texs = (const SkPoint*)reader.skip(
reed@android.com8a1c16f2008-12-17 15:59:43 +00001282 vCount * sizeof(SkPoint));
1283 }
1284 if (flags & DRAW_VERTICES_HAS_COLORS) {
reed@google.comddf98a82012-07-21 20:31:09 +00001285 colors = (const SkColor*)reader.skip(
reed@android.com8a1c16f2008-12-17 15:59:43 +00001286 vCount * sizeof(SkColor));
1287 }
1288 if (flags & DRAW_VERTICES_HAS_INDICES) {
reed@google.comddf98a82012-07-21 20:31:09 +00001289 iCount = reader.readInt();
1290 indices = (const uint16_t*)reader.skip(
reed@android.com8a1c16f2008-12-17 15:59:43 +00001291 iCount * sizeof(uint16_t));
1292 }
reed@google.com85e143c2013-12-30 15:51:25 +00001293 if (flags & DRAW_VERTICES_HAS_XFER) {
1294 int mode = reader.readInt();
1295 if (mode < 0 || mode > SkXfermode::kLastMode) {
1296 mode = SkXfermode::kModulate_Mode;
1297 }
1298 xfer.reset(SkXfermode::Create((SkXfermode::Mode)mode));
1299 }
1300 canvas.drawVertices(vmode, vCount, verts, texs, colors, xfer,
reed@android.com8a1c16f2008-12-17 15:59:43 +00001301 indices, iCount, paint);
1302 } break;
1303 case RESTORE:
1304 canvas.restore();
1305 break;
1306 case ROTATE:
reed@google.comddf98a82012-07-21 20:31:09 +00001307 canvas.rotate(reader.readScalar());
reed@android.com8a1c16f2008-12-17 15:59:43 +00001308 break;
1309 case SAVE:
Florin Malita5f6102d2014-06-30 10:13:28 -04001310 // SKPs with version < 29 also store a SaveFlags param.
1311 if (size > 4) {
1312 SkASSERT(8 == size);
1313 reader.readInt();
1314 }
1315 canvas.save();
reed@android.com8a1c16f2008-12-17 15:59:43 +00001316 break;
1317 case SAVE_LAYER: {
commit-bot@chromium.orgd7e0fbe2014-03-10 16:41:00 +00001318 const SkRect* boundsPtr = this->getRectPtr(reader);
1319 const SkPaint* paint = this->getPaint(reader);
reed@google.comddf98a82012-07-21 20:31:09 +00001320 canvas.saveLayer(boundsPtr, paint, (SkCanvas::SaveFlags) reader.readInt());
reed@android.com8a1c16f2008-12-17 15:59:43 +00001321 } break;
1322 case SCALE: {
reed@google.comddf98a82012-07-21 20:31:09 +00001323 SkScalar sx = reader.readScalar();
1324 SkScalar sy = reader.readScalar();
reed@android.com8a1c16f2008-12-17 15:59:43 +00001325 canvas.scale(sx, sy);
1326 } break;
reed@google.comb4c28192012-09-05 23:14:07 +00001327 case SET_MATRIX: {
1328 SkMatrix matrix;
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +00001329 this->getMatrix(reader, &matrix);
1330 matrix.postConcat(initialMatrix);
reed@google.comb4c28192012-09-05 23:14:07 +00001331 canvas.setMatrix(matrix);
1332 } break;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001333 case SKEW: {
reed@google.comddf98a82012-07-21 20:31:09 +00001334 SkScalar sx = reader.readScalar();
1335 SkScalar sy = reader.readScalar();
reed@android.com8a1c16f2008-12-17 15:59:43 +00001336 canvas.skew(sx, sy);
1337 } break;
1338 case TRANSLATE: {
reed@google.comddf98a82012-07-21 20:31:09 +00001339 SkScalar dx = reader.readScalar();
1340 SkScalar dy = reader.readScalar();
reed@android.com8a1c16f2008-12-17 15:59:43 +00001341 canvas.translate(dx, dy);
1342 } break;
1343 default:
1344 SkASSERT(0);
1345 }
rileya@google.com8515e792012-09-13 21:41:51 +00001346
robertphillips@google.com3f713722013-01-17 14:39:20 +00001347#ifdef SK_DEVELOPER
robertphillips@google.com6d9c92b2013-05-23 13:21:18 +00001348 this->postDraw(opIndex);
robertphillips@google.com6f6dfb42012-11-13 18:28:06 +00001349#endif
1350
rileya@google.com8515e792012-09-13 21:41:51 +00001351 if (it.isValid()) {
commit-bot@chromium.orga31eacb2014-04-28 20:17:48 +00001352 uint32_t skipTo = it.nextDraw();
robertphillips@google.com5f971142012-12-07 20:48:56 +00001353 if (kDrawComplete == skipTo) {
rileya@google.com1c6307e2012-09-14 15:52:47 +00001354 break;
1355 }
robertphillips@google.com5f971142012-12-07 20:48:56 +00001356 reader.setOffset(skipTo);
rileya@google.com8515e792012-09-13 21:41:51 +00001357 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001358 }
reed@google.com82065d62011-02-07 15:30:46 +00001359
reed@android.comae814c82009-02-13 14:56:09 +00001360#ifdef SPEW_CLIP_SKIPPING
1361 {
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +00001362 size_t size = skipRect.fSize + skipRRect.fSize + skipPath.fSize + skipRegion.fSize +
1363 skipCull.fSize;
1364 SkDebugf("--- Clip skips %d%% rect:%d rrect:%d path:%d rgn:%d cull:%d\n",
reed@google.com4ed0fb72012-12-12 20:48:18 +00001365 size * 100 / reader.offset(), skipRect.fCount, skipRRect.fCount,
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +00001366 skipPath.fCount, skipRegion.fCount, skipCull.fCount);
1367 SkDebugf("--- Total ops: %d\n", opCount);
reed@android.comae814c82009-02-13 14:56:09 +00001368 }
1369#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +00001370// this->dumpSize();
1371}
1372
robertphillips0bdbea72014-06-11 11:37:55 -07001373
1374#if SK_SUPPORT_GPU
egdaniel12c21982014-06-18 07:34:39 -07001375bool SkPicturePlayback::suitableForGpuRasterization(GrContext* context, const char **reason,
1376 int sampleCount) const {
robertphillips0bdbea72014-06-11 11:37:55 -07001377 // TODO: the heuristic used here needs to be refined
1378 static const int kNumPaintWithPathEffectUsesTol = 1;
1379 static const int kNumAAConcavePaths = 5;
1380
1381 SkASSERT(fContentInfo.numAAHairlineConcavePaths() <= fContentInfo.numAAConcavePaths());
1382
egdaniel12c21982014-06-18 07:34:39 -07001383 int numNonDashedPathEffects = fContentInfo.numPaintWithPathEffectUses() -
1384 fContentInfo.numFastPathDashEffects();
1385
1386 bool suitableForDash = (0 == fContentInfo.numPaintWithPathEffectUses()) ||
1387 (numNonDashedPathEffects < kNumPaintWithPathEffectUsesTol
1388 && 0 == sampleCount);
1389
1390 bool ret = suitableForDash &&
Mike Kleinc11530e2014-06-24 11:29:06 -04001391 (fContentInfo.numAAConcavePaths() - fContentInfo.numAAHairlineConcavePaths())
robertphillips0bdbea72014-06-11 11:37:55 -07001392 < kNumAAConcavePaths;
1393 if (!ret && NULL != reason) {
egdaniel12c21982014-06-18 07:34:39 -07001394 if (!suitableForDash) {
1395 if (0 != sampleCount) {
1396 *reason = "Can't use multisample on dash effect.";
1397 } else {
1398 *reason = "Too many non dashed path effects.";
1399 }
Mike Kleinc11530e2014-06-24 11:29:06 -04001400 } else if ((fContentInfo.numAAConcavePaths() - fContentInfo.numAAHairlineConcavePaths())
egdaniel12c21982014-06-18 07:34:39 -07001401 >= kNumAAConcavePaths)
robertphillips0bdbea72014-06-11 11:37:55 -07001402 *reason = "Too many anti-aliased concave paths.";
1403 else
1404 *reason = "Unknown reason for GPU unsuitability.";
1405 }
1406 return ret;
1407}
egdaniel12c21982014-06-18 07:34:39 -07001408
1409bool SkPicturePlayback::suitableForGpuRasterization(GrContext* context, const char **reason,
1410 GrPixelConfig config, SkScalar dpi) const {
1411
1412 if (context != NULL) {
1413 return this->suitableForGpuRasterization(context, reason,
1414 context->getRecommendedSampleCount(config, dpi));
1415 } else {
1416 return this->suitableForGpuRasterization(NULL, reason);
1417 }
1418}
1419
robertphillips0bdbea72014-06-11 11:37:55 -07001420#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +00001421///////////////////////////////////////////////////////////////////////////////
1422
reed@android.com8a1c16f2008-12-17 15:59:43 +00001423#ifdef SK_DEBUG_SIZE
reed@google.com82065d62011-02-07 15:30:46 +00001424int SkPicturePlayback::size(size_t* sizePtr) {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001425 int objects = bitmaps(sizePtr);
1426 objects += paints(sizePtr);
1427 objects += paths(sizePtr);
1428 objects += pictures(sizePtr);
1429 objects += regions(sizePtr);
reed@google.comddf98a82012-07-21 20:31:09 +00001430 *sizePtr = fOpData.size();
reed@google.com82065d62011-02-07 15:30:46 +00001431 return objects;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001432}
1433
1434int SkPicturePlayback::bitmaps(size_t* size) {
1435 size_t result = 0;
1436 for (int index = 0; index < fBitmapCount; index++) {
1437 // const SkBitmap& bitmap = fBitmaps[index];
1438 result += sizeof(SkBitmap); // bitmap->size();
1439 }
1440 *size = result;
1441 return fBitmapCount;
1442}
1443
1444int SkPicturePlayback::paints(size_t* size) {
1445 size_t result = 0;
1446 for (int index = 0; index < fPaintCount; index++) {
1447 // const SkPaint& paint = fPaints[index];
1448 result += sizeof(SkPaint); // paint->size();
1449 }
1450 *size = result;
1451 return fPaintCount;
1452}
1453
1454int SkPicturePlayback::paths(size_t* size) {
1455 size_t result = 0;
1456 for (int index = 0; index < fPathCount; index++) {
1457 const SkPath& path = fPaths[index];
1458 result += path.flatten(NULL);
1459 }
1460 *size = result;
1461 return fPathCount;
1462}
reed@android.com8a1c16f2008-12-17 15:59:43 +00001463#endif
1464
1465#ifdef SK_DEBUG_DUMP
1466void SkPicturePlayback::dumpBitmap(const SkBitmap& bitmap) const {
1467 char pBuffer[DUMP_BUFFER_SIZE];
1468 char* bufferPtr = pBuffer;
1469 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1470 "BitmapData bitmap%p = {", &bitmap);
1471 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1472 "{kWidth, %d}, ", bitmap.width());
1473 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1474 "{kHeight, %d}, ", bitmap.height());
1475 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1476 "{kRowBytes, %d}, ", bitmap.rowBytes());
1477// start here;
1478 SkDebugf("%s{0}};\n", pBuffer);
1479}
1480
1481void dumpMatrix(const SkMatrix& matrix) const {
1482 SkMatrix defaultMatrix;
1483 defaultMatrix.reset();
1484 char pBuffer[DUMP_BUFFER_SIZE];
1485 char* bufferPtr = pBuffer;
1486 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1487 "MatrixData matrix%p = {", &matrix);
1488 SkScalar scaleX = matrix.getScaleX();
1489 if (scaleX != defaultMatrix.getScaleX())
1490 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1491 "{kScaleX, %g}, ", SkScalarToFloat(scaleX));
1492 SkScalar scaleY = matrix.getScaleY();
1493 if (scaleY != defaultMatrix.getScaleY())
1494 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1495 "{kScaleY, %g}, ", SkScalarToFloat(scaleY));
1496 SkScalar skewX = matrix.getSkewX();
1497 if (skewX != defaultMatrix.getSkewX())
1498 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1499 "{kSkewX, %g}, ", SkScalarToFloat(skewX));
1500 SkScalar skewY = matrix.getSkewY();
1501 if (skewY != defaultMatrix.getSkewY())
1502 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1503 "{kSkewY, %g}, ", SkScalarToFloat(skewY));
1504 SkScalar translateX = matrix.getTranslateX();
1505 if (translateX != defaultMatrix.getTranslateX())
1506 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1507 "{kTranslateX, %g}, ", SkScalarToFloat(translateX));
1508 SkScalar translateY = matrix.getTranslateY();
1509 if (translateY != defaultMatrix.getTranslateY())
1510 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1511 "{kTranslateY, %g}, ", SkScalarToFloat(translateY));
1512 SkScalar perspX = matrix.getPerspX();
1513 if (perspX != defaultMatrix.getPerspX())
1514 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@google.com1915fd02013-12-19 14:22:03 +00001515 "{kPerspX, %g}, ", perspX);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001516 SkScalar perspY = matrix.getPerspY();
1517 if (perspY != defaultMatrix.getPerspY())
1518 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@google.com1915fd02013-12-19 14:22:03 +00001519 "{kPerspY, %g}, ", perspY);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001520 SkDebugf("%s{0}};\n", pBuffer);
1521}
1522
1523void dumpPaint(const SkPaint& paint) const {
1524 SkPaint defaultPaint;
1525 char pBuffer[DUMP_BUFFER_SIZE];
1526 char* bufferPtr = pBuffer;
1527 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1528 "PaintPointers paintPtrs%p = {", &paint);
1529 const SkTypeface* typeface = paint.getTypeface();
1530 if (typeface != defaultPaint.getTypeface())
1531 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1532 "{kTypeface, %p}, ", typeface);
1533 const SkPathEffect* pathEffect = paint.getPathEffect();
1534 if (pathEffect != defaultPaint.getPathEffect())
1535 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1536 "{kPathEffect, %p}, ", pathEffect);
1537 const SkShader* shader = paint.getShader();
1538 if (shader != defaultPaint.getShader())
1539 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1540 "{kShader, %p}, ", shader);
1541 const SkXfermode* xfermode = paint.getXfermode();
1542 if (xfermode != defaultPaint.getXfermode())
1543 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1544 "{kXfermode, %p}, ", xfermode);
1545 const SkMaskFilter* maskFilter = paint.getMaskFilter();
1546 if (maskFilter != defaultPaint.getMaskFilter())
1547 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1548 "{kMaskFilter, %p}, ", maskFilter);
1549 const SkColorFilter* colorFilter = paint.getColorFilter();
1550 if (colorFilter != defaultPaint.getColorFilter())
1551 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1552 "{kColorFilter, %p}, ", colorFilter);
1553 const SkRasterizer* rasterizer = paint.getRasterizer();
1554 if (rasterizer != defaultPaint.getRasterizer())
1555 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1556 "{kRasterizer, %p}, ", rasterizer);
1557 const SkDrawLooper* drawLooper = paint.getLooper();
1558 if (drawLooper != defaultPaint.getLooper())
1559 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1560 "{kDrawLooper, %p}, ", drawLooper);
1561 SkDebugf("%s{0}};\n", pBuffer);
1562 bufferPtr = pBuffer;
1563 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1564 "PaintScalars paintScalars%p = {", &paint);
1565 SkScalar textSize = paint.getTextSize();
1566 if (textSize != defaultPaint.getTextSize())
1567 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1568 "{kTextSize, %g}, ", SkScalarToFloat(textSize));
1569 SkScalar textScaleX = paint.getTextScaleX();
1570 if (textScaleX != defaultPaint.getTextScaleX())
1571 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1572 "{kTextScaleX, %g}, ", SkScalarToFloat(textScaleX));
1573 SkScalar textSkewX = paint.getTextSkewX();
1574 if (textSkewX != defaultPaint.getTextSkewX())
1575 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1576 "{kTextSkewX, %g}, ", SkScalarToFloat(textSkewX));
1577 SkScalar strokeWidth = paint.getStrokeWidth();
1578 if (strokeWidth != defaultPaint.getStrokeWidth())
1579 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1580 "{kStrokeWidth, %g}, ", SkScalarToFloat(strokeWidth));
1581 SkScalar strokeMiter = paint.getStrokeMiter();
1582 if (strokeMiter != defaultPaint.getStrokeMiter())
1583 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1584 "{kStrokeMiter, %g}, ", SkScalarToFloat(strokeMiter));
1585 SkDebugf("%s{0}};\n", pBuffer);
1586 bufferPtr = pBuffer;
1587 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1588 "PaintInts = paintInts%p = {", &paint);
1589 unsigned color = paint.getColor();
1590 if (color != defaultPaint.getColor())
1591 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1592 "{kColor, 0x%x}, ", color);
1593 unsigned flags = paint.getFlags();
1594 if (flags != defaultPaint.getFlags())
1595 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1596 "{kFlags, 0x%x}, ", flags);
1597 int align = paint.getTextAlign();
1598 if (align != defaultPaint.getTextAlign())
1599 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1600 "{kAlign, 0x%x}, ", align);
1601 int strokeCap = paint.getStrokeCap();
1602 if (strokeCap != defaultPaint.getStrokeCap())
1603 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1604 "{kStrokeCap, 0x%x}, ", strokeCap);
1605 int strokeJoin = paint.getStrokeJoin();
1606 if (strokeJoin != defaultPaint.getStrokeJoin())
1607 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1608 "{kAlign, 0x%x}, ", strokeJoin);
1609 int style = paint.getStyle();
1610 if (style != defaultPaint.getStyle())
1611 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1612 "{kStyle, 0x%x}, ", style);
1613 int textEncoding = paint.getTextEncoding();
1614 if (textEncoding != defaultPaint.getTextEncoding())
1615 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1616 "{kTextEncoding, 0x%x}, ", textEncoding);
1617 SkDebugf("%s{0}};\n", pBuffer);
1618
1619 SkDebugf("PaintData paint%p = {paintPtrs%p, paintScalars%p, paintInts%p};\n",
1620 &paint, &paint, &paint, &paint);
1621}
1622
1623void SkPicturePlayback::dumpPath(const SkPath& path) const {
1624 SkDebugf("path dump unimplemented\n");
1625}
1626
1627void SkPicturePlayback::dumpPicture(const SkPicture& picture) const {
1628 SkDebugf("picture dump unimplemented\n");
1629}
1630
1631void SkPicturePlayback::dumpRegion(const SkRegion& region) const {
1632 SkDebugf("region dump unimplemented\n");
1633}
1634
1635int SkPicturePlayback::dumpDrawType(char* bufferPtr, char* buffer, DrawType drawType) {
1636 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1637 "k%s, ", DrawTypeToString(drawType));
1638}
1639
1640int SkPicturePlayback::dumpInt(char* bufferPtr, char* buffer, char* name) {
1641 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1642 "%s:%d, ", name, getInt());
1643}
1644
1645int SkPicturePlayback::dumpRect(char* bufferPtr, char* buffer, char* name) {
1646 const SkRect* rect = fReader.skipRect();
1647 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
reed@google.com82065d62011-02-07 15:30:46 +00001648 "%s:{l:%g t:%g r:%g b:%g}, ", name, SkScalarToFloat(rect.fLeft),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001649 SkScalarToFloat(rect.fTop),
1650 SkScalarToFloat(rect.fRight), SkScalarToFloat(rect.fBottom));
1651}
1652
1653int SkPicturePlayback::dumpPoint(char* bufferPtr, char* buffer, char* name) {
1654 SkPoint pt;
1655 getPoint(&pt);
1656 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
reed@google.com82065d62011-02-07 15:30:46 +00001657 "%s:{x:%g y:%g}, ", name, SkScalarToFloat(pt.fX),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001658 SkScalarToFloat(pt.fY));
1659}
1660
1661void SkPicturePlayback::dumpPointArray(char** bufferPtrPtr, char* buffer, int count) {
1662 char* bufferPtr = *bufferPtrPtr;
1663 const SkPoint* pts = (const SkPoint*)fReadStream.getAtPos();
1664 fReadStream.skip(sizeof(SkPoint) * count);
1665 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1666 "count:%d {", count);
1667 for (int index = 0; index < count; index++)
1668 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
reed@google.com82065d62011-02-07 15:30:46 +00001669 "{x:%g y:%g}, ", SkScalarToFloat(pts[index].fX),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001670 SkScalarToFloat(pts[index].fY));
1671 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1672 "} ");
1673 *bufferPtrPtr = bufferPtr;
1674}
1675
1676int SkPicturePlayback::dumpPtr(char* bufferPtr, char* buffer, char* name, void* ptr) {
1677 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1678 "%s:%p, ", name, ptr);
1679}
1680
1681int SkPicturePlayback::dumpRectPtr(char* bufferPtr, char* buffer, char* name) {
1682 char result;
1683 fReadStream.read(&result, sizeof(result));
1684 if (result)
1685 return dumpRect(bufferPtr, buffer, name);
1686 else
1687 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1688 "%s:NULL, ", name);
1689}
1690
1691int SkPicturePlayback::dumpScalar(char* bufferPtr, char* buffer, char* name) {
1692 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1693 "%s:%d, ", name, getScalar());
1694}
1695
1696void SkPicturePlayback::dumpText(char** bufferPtrPtr, char* buffer) {
1697 char* bufferPtr = *bufferPtrPtr;
1698 int length = getInt();
1699 bufferPtr += dumpDrawType(bufferPtr, buffer);
1700 fReadStream.skipToAlign4();
1701 char* text = (char*) fReadStream.getAtPos();
1702 fReadStream.skip(length);
1703 bufferPtr += dumpInt(bufferPtr, buffer, "length");
1704 int limit = DUMP_BUFFER_SIZE - (bufferPtr - buffer) - 2;
1705 length >>= 1;
1706 if (limit > length)
1707 limit = length;
1708 if (limit > 0) {
1709 *bufferPtr++ = '"';
1710 for (int index = 0; index < limit; index++) {
1711 *bufferPtr++ = *(unsigned short*) text;
1712 text += sizeof(unsigned short);
1713 }
1714 *bufferPtr++ = '"';
1715 }
1716 *bufferPtrPtr = bufferPtr;
1717}
1718
1719#define DUMP_DRAWTYPE(drawType) \
1720 bufferPtr += dumpDrawType(bufferPtr, buffer, drawType)
1721
1722#define DUMP_INT(name) \
1723 bufferPtr += dumpInt(bufferPtr, buffer, #name)
1724
1725#define DUMP_RECT_PTR(name) \
1726 bufferPtr += dumpRectPtr(bufferPtr, buffer, #name)
1727
1728#define DUMP_POINT(name) \
1729 bufferPtr += dumpRect(bufferPtr, buffer, #name)
1730
1731#define DUMP_RECT(name) \
1732 bufferPtr += dumpRect(bufferPtr, buffer, #name)
1733
1734#define DUMP_POINT_ARRAY(count) \
1735 dumpPointArray(&bufferPtr, buffer, count)
1736
1737#define DUMP_PTR(name, ptr) \
1738 bufferPtr += dumpPtr(bufferPtr, buffer, #name, (void*) ptr)
1739
1740#define DUMP_SCALAR(name) \
1741 bufferPtr += dumpScalar(bufferPtr, buffer, #name)
1742
1743#define DUMP_TEXT() \
1744 dumpText(&bufferPtr, buffer)
1745
1746void SkPicturePlayback::dumpStream() {
1747 SkDebugf("RecordStream stream = {\n");
1748 DrawType drawType;
1749 TextContainer text;
1750 fReadStream.rewind();
1751 char buffer[DUMP_BUFFER_SIZE], * bufferPtr;
1752 while (fReadStream.read(&drawType, sizeof(drawType))) {
1753 bufferPtr = buffer;
1754 DUMP_DRAWTYPE(drawType);
1755 switch (drawType) {
1756 case CLIP_PATH: {
1757 DUMP_PTR(SkPath, &getPath());
1758 DUMP_INT(SkRegion::Op);
1759 DUMP_INT(offsetToRestore);
1760 } break;
1761 case CLIP_REGION: {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001762 DUMP_INT(SkRegion::Op);
1763 DUMP_INT(offsetToRestore);
1764 } break;
1765 case CLIP_RECT: {
1766 DUMP_RECT(rect);
1767 DUMP_INT(SkRegion::Op);
1768 DUMP_INT(offsetToRestore);
1769 } break;
1770 case CONCAT:
reed@android.com8a1c16f2008-12-17 15:59:43 +00001771 break;
1772 case DRAW_BITMAP: {
1773 DUMP_PTR(SkPaint, getPaint());
1774 DUMP_PTR(SkBitmap, &getBitmap());
1775 DUMP_SCALAR(left);
1776 DUMP_SCALAR(top);
1777 } break;
1778 case DRAW_PAINT:
1779 DUMP_PTR(SkPaint, getPaint());
1780 break;
1781 case DRAW_PATH: {
1782 DUMP_PTR(SkPaint, getPaint());
1783 DUMP_PTR(SkPath, &getPath());
1784 } break;
1785 case DRAW_PICTURE: {
1786 DUMP_PTR(SkPicture, &getPicture());
1787 } break;
1788 case DRAW_POINTS: {
1789 DUMP_PTR(SkPaint, getPaint());
1790 (void)getInt(); // PointMode
1791 size_t count = getInt();
1792 fReadStream.skipToAlign4();
1793 DUMP_POINT_ARRAY(count);
1794 } break;
1795 case DRAW_POS_TEXT: {
1796 DUMP_PTR(SkPaint, getPaint());
1797 DUMP_TEXT();
1798 size_t points = getInt();
1799 fReadStream.skipToAlign4();
1800 DUMP_POINT_ARRAY(points);
1801 } break;
1802 case DRAW_POS_TEXT_H: {
1803 DUMP_PTR(SkPaint, getPaint());
1804 DUMP_TEXT();
1805 size_t points = getInt();
1806 fReadStream.skipToAlign4();
1807 DUMP_SCALAR(top);
1808 DUMP_SCALAR(bottom);
1809 DUMP_SCALAR(constY);
1810 DUMP_POINT_ARRAY(points);
1811 } break;
1812 case DRAW_RECT: {
1813 DUMP_PTR(SkPaint, getPaint());
1814 DUMP_RECT(rect);
1815 } break;
1816 case DRAW_SPRITE: {
1817 DUMP_PTR(SkPaint, getPaint());
1818 DUMP_PTR(SkBitmap, &getBitmap());
1819 DUMP_SCALAR(left);
1820 DUMP_SCALAR(top);
1821 } break;
1822 case DRAW_TEXT: {
1823 DUMP_PTR(SkPaint, getPaint());
1824 DUMP_TEXT();
1825 DUMP_SCALAR(x);
1826 DUMP_SCALAR(y);
1827 } break;
1828 case DRAW_TEXT_ON_PATH: {
1829 DUMP_PTR(SkPaint, getPaint());
1830 DUMP_TEXT();
1831 DUMP_PTR(SkPath, &getPath());
reed@android.com8a1c16f2008-12-17 15:59:43 +00001832 } break;
1833 case RESTORE:
1834 break;
1835 case ROTATE:
1836 DUMP_SCALAR(rotate);
1837 break;
1838 case SAVE:
1839 DUMP_INT(SkCanvas::SaveFlags);
1840 break;
1841 case SAVE_LAYER: {
1842 DUMP_RECT_PTR(layer);
1843 DUMP_PTR(SkPaint, getPaint());
1844 DUMP_INT(SkCanvas::SaveFlags);
1845 } break;
1846 case SCALE: {
1847 DUMP_SCALAR(sx);
1848 DUMP_SCALAR(sy);
1849 } break;
1850 case SKEW: {
1851 DUMP_SCALAR(sx);
1852 DUMP_SCALAR(sy);
1853 } break;
1854 case TRANSLATE: {
1855 DUMP_SCALAR(dx);
1856 DUMP_SCALAR(dy);
1857 } break;
1858 default:
1859 SkASSERT(0);
1860 }
1861 SkDebugf("%s\n", buffer);
1862 }
1863}
1864
1865void SkPicturePlayback::dump() const {
1866 char pBuffer[DUMP_BUFFER_SIZE];
1867 char* bufferPtr = pBuffer;
1868 int index;
1869 if (fBitmapCount > 0)
1870 SkDebugf("// bitmaps (%d)\n", fBitmapCount);
1871 for (index = 0; index < fBitmapCount; index++) {
1872 const SkBitmap& bitmap = fBitmaps[index];
1873 dumpBitmap(bitmap);
1874 }
1875 if (fBitmapCount > 0)
reed@google.com82065d62011-02-07 15:30:46 +00001876 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001877 "Bitmaps bitmaps = {");
1878 for (index = 0; index < fBitmapCount; index++)
reed@google.com82065d62011-02-07 15:30:46 +00001879 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001880 "bitmap%p, ", &fBitmaps[index]);
1881 if (fBitmapCount > 0)
1882 SkDebugf("%s0};\n", pBuffer);
1883
reed@android.com8a1c16f2008-12-17 15:59:43 +00001884
1885 if (fPaintCount > 0)
1886 SkDebugf("// paints (%d)\n", fPaintCount);
1887 for (index = 0; index < fPaintCount; index++) {
1888 const SkPaint& paint = fPaints[index];
1889 dumpPaint(paint);
1890 }
1891 bufferPtr = pBuffer;
1892 if (fPaintCount > 0)
reed@google.com82065d62011-02-07 15:30:46 +00001893 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001894 "Paints paints = {");
1895 for (index = 0; index < fPaintCount; index++)
reed@google.com82065d62011-02-07 15:30:46 +00001896 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001897 "paint%p, ", &fPaints[index]);
1898 if (fPaintCount > 0)
1899 SkDebugf("%s0};\n", pBuffer);
1900
1901 for (index = 0; index < fPathCount; index++) {
1902 const SkPath& path = fPaths[index];
1903 dumpPath(path);
1904 }
1905 bufferPtr = pBuffer;
1906 if (fPathCount > 0)
reed@google.com82065d62011-02-07 15:30:46 +00001907 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001908 "Paths paths = {");
1909 for (index = 0; index < fPathCount; index++)
reed@google.com82065d62011-02-07 15:30:46 +00001910 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001911 "path%p, ", &fPaths[index]);
1912 if (fPathCount > 0)
1913 SkDebugf("%s0};\n", pBuffer);
1914
1915 for (index = 0; index < fPictureCount; index++) {
1916 dumpPicture(*fPictureRefs[index]);
1917 }
1918 bufferPtr = pBuffer;
1919 if (fPictureCount > 0)
reed@google.com82065d62011-02-07 15:30:46 +00001920 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001921 "Pictures pictures = {");
1922 for (index = 0; index < fPictureCount; index++)
reed@google.com82065d62011-02-07 15:30:46 +00001923 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001924 "picture%p, ", fPictureRefs[index]);
1925 if (fPictureCount > 0)
1926 SkDebugf("%s0};\n", pBuffer);
1927
reed@android.com8a1c16f2008-12-17 15:59:43 +00001928 const_cast<SkPicturePlayback*>(this)->dumpStream();
1929}
1930
1931#endif