blob: d54a6c5f3b3384d99499e6966dd139b4fce280e5 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#include "SkPicturePlayback.h"
9#include "SkPictureRecord.h"
10#include "SkTypeface.h"
djsollen@google.com2b2ede32012-04-12 13:24:04 +000011#include "SkOrderedReadBuffer.h"
12#include "SkOrderedWriteBuffer.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000013#include <new>
rileya@google.com8515e792012-09-13 21:41:51 +000014#include "SkBBoxHierarchy.h"
15#include "SkPictureStateTree.h"
16#include "SkTSort.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000017
reed@google.comf4cc1872012-07-23 15:04:45 +000018template <typename T> int SafeCount(const T* obj) {
19 return obj ? obj->count() : 0;
20}
21
reed@android.comae814c82009-02-13 14:56:09 +000022/* Define this to spew out a debug statement whenever we skip the remainder of
23 a save/restore block because a clip... command returned false (empty).
24 */
25#define SPEW_CLIP_SKIPPINGx
26
reed@android.com8a1c16f2008-12-17 15:59:43 +000027SkPicturePlayback::SkPicturePlayback() {
28 this->init();
29}
30
djsollen@google.comc9ab9872012-08-29 18:52:07 +000031SkPicturePlayback::SkPicturePlayback(const SkPictureRecord& record, bool deepCopy) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000032#ifdef SK_DEBUG_SIZE
reed@google.com82065d62011-02-07 15:30:46 +000033 size_t overallBytes, bitmapBytes, matricesBytes,
reed@android.com8a1c16f2008-12-17 15:59:43 +000034 paintBytes, pathBytes, pictureBytes, regionBytes;
35 int bitmaps = record.bitmaps(&bitmapBytes);
36 int matrices = record.matrices(&matricesBytes);
37 int paints = record.paints(&paintBytes);
38 int paths = record.paths(&pathBytes);
39 int pictures = record.pictures(&pictureBytes);
40 int regions = record.regions(&regionBytes);
41 SkDebugf("picture record mem used %zd (stream %zd) ", record.size(),
42 record.streamlen());
43 if (bitmaps != 0)
44 SkDebugf("bitmaps size %zd (bitmaps:%d) ", bitmapBytes, bitmaps);
45 if (matrices != 0)
46 SkDebugf("matrices size %zd (matrices:%d) ", matricesBytes, matrices);
47 if (paints != 0)
48 SkDebugf("paints size %zd (paints:%d) ", paintBytes, paints);
49 if (paths != 0)
50 SkDebugf("paths size %zd (paths:%d) ", pathBytes, paths);
51 if (pictures != 0)
52 SkDebugf("pictures size %zd (pictures:%d) ", pictureBytes, pictures);
53 if (regions != 0)
54 SkDebugf("regions size %zd (regions:%d) ", regionBytes, regions);
55 if (record.fPointWrites != 0)
56 SkDebugf("points size %zd (points:%d) ", record.fPointBytes, record.fPointWrites);
57 if (record.fRectWrites != 0)
58 SkDebugf("rects size %zd (rects:%d) ", record.fRectBytes, record.fRectWrites);
59 if (record.fTextWrites != 0)
60 SkDebugf("text size %zd (text strings:%d) ", record.fTextBytes, record.fTextWrites);
reed@google.com82065d62011-02-07 15:30:46 +000061
reed@android.com8a1c16f2008-12-17 15:59:43 +000062 SkDebugf("\n");
63#endif
64#ifdef SK_DEBUG_DUMP
65 record.dumpMatrices();
66 record.dumpPaints();
67#endif
68
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +000069 record.validate(record.writeStream().size(), 0);
reed@android.com8a1c16f2008-12-17 15:59:43 +000070 const SkWriter32& writer = record.writeStream();
71 init();
scroggo@google.comd614c6a2012-09-14 17:26:37 +000072 if (writer.size() == 0) {
73 fOpData = SkData::NewEmpty();
reed@android.com8a1c16f2008-12-17 15:59:43 +000074 return;
scroggo@google.comd614c6a2012-09-14 17:26:37 +000075 }
reed@google.com82065d62011-02-07 15:30:46 +000076
rileya@google.com8515e792012-09-13 21:41:51 +000077 fBoundingHierarchy = record.fBoundingHierarchy;
78 fStateTree = record.fStateTree;
79
80 SkSafeRef(fBoundingHierarchy);
81 SkSafeRef(fStateTree);
82
83 if (NULL != fBoundingHierarchy) {
84 fBoundingHierarchy->flushDeferredInserts();
85 }
86
reed@android.com8a1c16f2008-12-17 15:59:43 +000087 {
88 size_t size = writer.size();
89 void* buffer = sk_malloc_throw(size);
90 writer.flatten(buffer);
reed@google.comddf98a82012-07-21 20:31:09 +000091 SkASSERT(!fOpData);
92 fOpData = SkData::NewFromMalloc(buffer, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +000093 }
reed@google.com82065d62011-02-07 15:30:46 +000094
reed@android.com8a1c16f2008-12-17 15:59:43 +000095 // copy over the refcnt dictionary to our reader
djsollen@google.com21830d92012-08-07 19:49:41 +000096 record.fFlattenableHeap.setupPlaybacks();
reed@android.com8a1c16f2008-12-17 15:59:43 +000097
djsollen@google.comc9ab9872012-08-29 18:52:07 +000098 fBitmaps = record.fBitmapHeap->extractBitmaps();
djsollen@google.com21830d92012-08-07 19:49:41 +000099 fMatrices = record.fMatrices.unflattenToArray();
100 fPaints = record.fPaints.unflattenToArray();
101 fRegions = record.fRegions.unflattenToArray();
102
djsollen@google.comc9ab9872012-08-29 18:52:07 +0000103 fBitmapHeap.reset(SkSafeRef(record.fBitmapHeap));
104 fPathHeap.reset(SkSafeRef(record.fPathHeap));
105
106 // ensure that the paths bounds are pre-computed
107 if (fPathHeap.get()) {
108 for (int i = 0; i < fPathHeap->count(); i++) {
109 (*fPathHeap)[i].updateBoundsCache();
110 }
111 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000112
113 const SkTDArray<SkPicture* >& pictures = record.getPictureRefs();
114 fPictureCount = pictures.count();
115 if (fPictureCount > 0) {
116 fPictureRefs = SkNEW_ARRAY(SkPicture*, fPictureCount);
117 for (int i = 0; i < fPictureCount; i++) {
djsollen@google.comc9ab9872012-08-29 18:52:07 +0000118 if (deepCopy) {
119 fPictureRefs[i] = pictures[i]->clone();
120 } else {
121 fPictureRefs[i] = pictures[i];
122 fPictureRefs[i]->ref();
123 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000124 }
125 }
reed@google.com82065d62011-02-07 15:30:46 +0000126
reed@android.com8a1c16f2008-12-17 15:59:43 +0000127#ifdef SK_DEBUG_SIZE
128 int overall = fPlayback->size(&overallBytes);
129 bitmaps = fPlayback->bitmaps(&bitmapBytes);
130 paints = fPlayback->paints(&paintBytes);
131 paths = fPlayback->paths(&pathBytes);
132 pictures = fPlayback->pictures(&pictureBytes);
133 regions = fPlayback->regions(&regionBytes);
134 SkDebugf("playback size %zd (objects:%d) ", overallBytes, overall);
135 if (bitmaps != 0)
136 SkDebugf("bitmaps size %zd (bitmaps:%d) ", bitmapBytes, bitmaps);
137 if (paints != 0)
138 SkDebugf("paints size %zd (paints:%d) ", paintBytes, paints);
139 if (paths != 0)
140 SkDebugf("paths size %zd (paths:%d) ", pathBytes, paths);
141 if (pictures != 0)
142 SkDebugf("pictures size %zd (pictures:%d) ", pictureBytes, pictures);
143 if (regions != 0)
144 SkDebugf("regions size %zd (regions:%d) ", regionBytes, regions);
145 SkDebugf("\n");
146#endif
147}
148
reed@google.comdee54be2012-12-10 17:39:36 +0000149static bool needs_deep_copy(const SkPaint& paint) {
150 /*
151 * These fields are known to be immutable, and so can be shallow-copied
152 *
153 * getTypeface();
154 * getAnnotation();
155 */
156
157 return paint.getPathEffect() ||
158 paint.getShader() ||
159 paint.getXfermode() ||
160 paint.getMaskFilter() ||
161 paint.getColorFilter() ||
162 paint.getRasterizer() ||
163 paint.getLooper() ||
164 paint.getImageFilter();
165}
166
djsollen@google.comc9ab9872012-08-29 18:52:07 +0000167SkPicturePlayback::SkPicturePlayback(const SkPicturePlayback& src, SkPictCopyInfo* deepCopyInfo) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000168 this->init();
169
djsollen@google.comc9ab9872012-08-29 18:52:07 +0000170 fBitmapHeap.reset(SkSafeRef(src.fBitmapHeap.get()));
171 fPathHeap.reset(SkSafeRef(src.fPathHeap.get()));
172
173 fMatrices = SkSafeRef(src.fMatrices);
174 fRegions = SkSafeRef(src.fRegions);
175 fOpData = SkSafeRef(src.fOpData);
skia.committer@gmail.com1d225f22012-09-14 02:01:10 +0000176
rileya@google.com8515e792012-09-13 21:41:51 +0000177 fBoundingHierarchy = src.fBoundingHierarchy;
178 fStateTree = src.fStateTree;
179
180 SkSafeRef(fBoundingHierarchy);
181 SkSafeRef(fStateTree);
djsollen@google.comc9ab9872012-08-29 18:52:07 +0000182
183 if (deepCopyInfo) {
junov@chromium.org94f20dc2013-01-28 21:04:44 +0000184 int paintCount = SafeCount(src.fPaints);
djsollen@google.comc9ab9872012-08-29 18:52:07 +0000185
186 if (src.fBitmaps) {
187 fBitmaps = SkTRefArray<SkBitmap>::Create(src.fBitmaps->begin(), src.fBitmaps->count());
188 }
189
190 if (!deepCopyInfo->initialized) {
191 /* The alternative to doing this is to have a clone method on the paint and have it make
192 * the deep copy of its internal structures as needed. The holdup to doing that is at
193 * this point we would need to pass the SkBitmapHeap so that we don't unnecessarily
194 * flatten the pixels in a bitmap shader.
195 */
junov@chromium.org94f20dc2013-01-28 21:04:44 +0000196 deepCopyInfo->paintData.setCount(paintCount);
djsollen@google.comc9ab9872012-08-29 18:52:07 +0000197
scroggo@google.com6f928622012-12-10 18:20:23 +0000198 /* Use an SkBitmapHeap to avoid flattening bitmaps in shaders. If there already is one,
199 * use it. If this SkPicturePlayback was created from a stream, fBitmapHeap will be
200 * NULL, so create a new one.
201 */
202 if (fBitmapHeap.get() == NULL) {
203 // FIXME: Put this on the stack inside SkPicture::clone. Further, is it possible to
204 // do the rest of this initialization in SkPicture::clone as well?
205 SkBitmapHeap* heap = SkNEW(SkBitmapHeap);
206 deepCopyInfo->controller.setBitmapStorage(heap);
207 heap->unref();
208 } else {
209 deepCopyInfo->controller.setBitmapStorage(fBitmapHeap);
210 }
211
djsollen@google.comc9ab9872012-08-29 18:52:07 +0000212 SkDEBUGCODE(int heapSize = SafeCount(fBitmapHeap.get());)
junov@chromium.org94f20dc2013-01-28 21:04:44 +0000213 for (int i = 0; i < paintCount; i++) {
reed@google.comdee54be2012-12-10 17:39:36 +0000214 if (needs_deep_copy(src.fPaints->at(i))) {
215 deepCopyInfo->paintData[i] = SkFlatData::Create(&deepCopyInfo->controller,
216 &src.fPaints->at(i), 0,
217 &SkFlattenObjectProc<SkPaint>);
218 } else {
219 // this is our sentinel, which we use in the unflatten loop
220 deepCopyInfo->paintData[i] = NULL;
221 }
djsollen@google.comc9ab9872012-08-29 18:52:07 +0000222 }
223 SkASSERT(SafeCount(fBitmapHeap.get()) == heapSize);
224
225 // needed to create typeface playback
226 deepCopyInfo->controller.setupPlaybacks();
227 deepCopyInfo->initialized = true;
228 }
229
junov@chromium.org94f20dc2013-01-28 21:04:44 +0000230 fPaints = SkTRefArray<SkPaint>::Create(paintCount);
231 SkASSERT(deepCopyInfo->paintData.count() == paintCount);
reed@google.comdee54be2012-12-10 17:39:36 +0000232 SkBitmapHeap* bmHeap = deepCopyInfo->controller.getBitmapHeap();
233 SkTypefacePlayback* tfPlayback = deepCopyInfo->controller.getTypefacePlayback();
junov@chromium.org94f20dc2013-01-28 21:04:44 +0000234 for (int i = 0; i < paintCount; i++) {
reed@google.comdee54be2012-12-10 17:39:36 +0000235 if (deepCopyInfo->paintData[i]) {
236 deepCopyInfo->paintData[i]->unflatten(&fPaints->writableAt(i),
237 &SkUnflattenObjectProc<SkPaint>,
238 bmHeap, tfPlayback);
239 } else {
240 // needs_deep_copy was false, so just need to assign
241 fPaints->writableAt(i) = src.fPaints->at(i);
242 }
djsollen@google.comc9ab9872012-08-29 18:52:07 +0000243 }
244
245 } else {
246 fBitmaps = SkSafeRef(src.fBitmaps);
247 fPaints = SkSafeRef(src.fPaints);
248 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000249
250 fPictureCount = src.fPictureCount;
251 fPictureRefs = SkNEW_ARRAY(SkPicture*, fPictureCount);
252 for (int i = 0; i < fPictureCount; i++) {
djsollen@google.comc9ab9872012-08-29 18:52:07 +0000253 if (deepCopyInfo) {
254 fPictureRefs[i] = src.fPictureRefs[i]->clone();
255 } else {
256 fPictureRefs[i] = src.fPictureRefs[i];
257 fPictureRefs[i]->ref();
258 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000259 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000260}
261
262void SkPicturePlayback::init() {
263 fBitmaps = NULL;
264 fMatrices = NULL;
265 fPaints = NULL;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000266 fPictureRefs = NULL;
267 fRegions = NULL;
reed@google.comf4cc1872012-07-23 15:04:45 +0000268 fPictureCount = 0;
reed@google.comddf98a82012-07-21 20:31:09 +0000269 fOpData = NULL;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000270 fFactoryPlayback = NULL;
rileya@google.com8515e792012-09-13 21:41:51 +0000271 fBoundingHierarchy = NULL;
272 fStateTree = NULL;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000273}
274
275SkPicturePlayback::~SkPicturePlayback() {
reed@google.comddf98a82012-07-21 20:31:09 +0000276 fOpData->unref();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000277
reed@google.comf4cc1872012-07-23 15:04:45 +0000278 SkSafeUnref(fBitmaps);
279 SkSafeUnref(fMatrices);
280 SkSafeUnref(fPaints);
281 SkSafeUnref(fRegions);
rileya@google.com8515e792012-09-13 21:41:51 +0000282 SkSafeUnref(fBoundingHierarchy);
283 SkSafeUnref(fStateTree);
reed@google.com82065d62011-02-07 15:30:46 +0000284
reed@android.com8a1c16f2008-12-17 15:59:43 +0000285 for (int i = 0; i < fPictureCount; i++) {
286 fPictureRefs[i]->unref();
287 }
288 SkDELETE_ARRAY(fPictureRefs);
reed@google.com82065d62011-02-07 15:30:46 +0000289
reed@android.com8a1c16f2008-12-17 15:59:43 +0000290 SkDELETE(fFactoryPlayback);
291}
292
293void SkPicturePlayback::dumpSize() const {
294 SkDebugf("--- picture size: ops=%d bitmaps=%d [%d] matrices=%d [%d] paints=%d [%d] paths=%d regions=%d\n",
reed@google.comddf98a82012-07-21 20:31:09 +0000295 fOpData->size(),
reed@google.comf4cc1872012-07-23 15:04:45 +0000296 SafeCount(fBitmaps), SafeCount(fBitmaps) * sizeof(SkBitmap),
297 SafeCount(fMatrices), SafeCount(fMatrices) * sizeof(SkMatrix),
298 SafeCount(fPaints), SafeCount(fPaints) * sizeof(SkPaint),
djsollen@google.comc9ab9872012-08-29 18:52:07 +0000299 SafeCount(fPathHeap.get()),
reed@google.comf4cc1872012-07-23 15:04:45 +0000300 SafeCount(fRegions));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000301}
302
303///////////////////////////////////////////////////////////////////////////////
304///////////////////////////////////////////////////////////////////////////////
305
reed@android.com8a1c16f2008-12-17 15:59:43 +0000306#define PICT_READER_TAG SkSetFourByteTag('r', 'e', 'a', 'd')
307#define PICT_FACTORY_TAG SkSetFourByteTag('f', 'a', 'c', 't')
308#define PICT_TYPEFACE_TAG SkSetFourByteTag('t', 'p', 'f', 'c')
309#define PICT_PICTURE_TAG SkSetFourByteTag('p', 'c', 't', 'r')
reed@google.com67562092012-06-22 15:38:39 +0000310
311// This tag specifies the size of the ReadBuffer, needed for the following tags
312#define PICT_BUFFER_SIZE_TAG SkSetFourByteTag('a', 'r', 'a', 'y')
reed@android.com8a1c16f2008-12-17 15:59:43 +0000313// these are all inside the ARRAYS tag
reed@google.com67562092012-06-22 15:38:39 +0000314#define PICT_BITMAP_BUFFER_TAG SkSetFourByteTag('b', 't', 'm', 'p')
315#define PICT_MATRIX_BUFFER_TAG SkSetFourByteTag('m', 't', 'r', 'x')
316#define PICT_PAINT_BUFFER_TAG SkSetFourByteTag('p', 'n', 't', ' ')
317#define PICT_PATH_BUFFER_TAG SkSetFourByteTag('p', 't', 'h', ' ')
318#define PICT_REGION_BUFFER_TAG SkSetFourByteTag('r', 'g', 'n', ' ')
reed@android.com8a1c16f2008-12-17 15:59:43 +0000319
reed@google.comed384952012-06-22 13:12:17 +0000320// Always write this guy last (with no length field afterwards)
321#define PICT_EOF_TAG SkSetFourByteTag('e', 'o', 'f', ' ')
322
reed@android.com8a1c16f2008-12-17 15:59:43 +0000323#include "SkStream.h"
324
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000325static void writeTagSize(SkOrderedWriteBuffer& buffer, uint32_t tag,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000326 uint32_t size) {
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000327 buffer.writeUInt(tag);
328 buffer.writeUInt(size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000329}
330
331static void writeTagSize(SkWStream* stream, uint32_t tag,
332 uint32_t size) {
333 stream->write32(tag);
334 stream->write32(size);
335}
336
mike@reedtribe.orge9e08cc2011-04-29 01:44:52 +0000337static void writeFactories(SkWStream* stream, const SkFactorySet& rec) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000338 int count = rec.count();
reed@google.com82065d62011-02-07 15:30:46 +0000339
reed@android.com8a1c16f2008-12-17 15:59:43 +0000340 writeTagSize(stream, PICT_FACTORY_TAG, count);
reed@google.com82065d62011-02-07 15:30:46 +0000341
reed@android.com8a1c16f2008-12-17 15:59:43 +0000342 SkAutoSTMalloc<16, SkFlattenable::Factory> storage(count);
343 SkFlattenable::Factory* array = (SkFlattenable::Factory*)storage.get();
mike@reedtribe.orge9e08cc2011-04-29 01:44:52 +0000344 rec.copyToArray(array);
reed@google.com82065d62011-02-07 15:30:46 +0000345
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 {
352 uint32_t len = strlen(name);
353 stream->writePackedUInt(len);
354 stream->write(name, len);
355 }
356 }
357}
358
mike@reedtribe.orge9e08cc2011-04-29 01:44:52 +0000359static void writeTypefaces(SkWStream* stream, const SkRefCntSet& rec) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000360 int count = rec.count();
reed@google.com82065d62011-02-07 15:30:46 +0000361
reed@android.com8a1c16f2008-12-17 15:59:43 +0000362 writeTagSize(stream, PICT_TYPEFACE_TAG, count);
reed@google.com82065d62011-02-07 15:30:46 +0000363
reed@android.com8a1c16f2008-12-17 15:59:43 +0000364 SkAutoSTMalloc<16, SkTypeface*> storage(count);
365 SkTypeface** array = (SkTypeface**)storage.get();
mike@reedtribe.orge9e08cc2011-04-29 01:44:52 +0000366 rec.copyToArray((SkRefCnt**)array);
reed@google.com82065d62011-02-07 15:30:46 +0000367
reed@android.com8a1c16f2008-12-17 15:59:43 +0000368 for (int i = 0; i < count; i++) {
369 array[i]->serialize(stream);
370 }
371}
372
reed@google.com67562092012-06-22 15:38:39 +0000373void SkPicturePlayback::flattenToBuffer(SkOrderedWriteBuffer& buffer) const {
reed@google.comf4cc1872012-07-23 15:04:45 +0000374 int i, n;
reed@google.com82065d62011-02-07 15:30:46 +0000375
reed@google.comf4cc1872012-07-23 15:04:45 +0000376 if ((n = SafeCount(fBitmaps)) > 0) {
377 writeTagSize(buffer, PICT_BITMAP_BUFFER_TAG, n);
378 for (i = 0; i < n; i++) {
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000379 buffer.writeBitmap((*fBitmaps)[i]);
reed@google.com67562092012-06-22 15:38:39 +0000380 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000381 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000382
reed@google.comf4cc1872012-07-23 15:04:45 +0000383 if ((n = SafeCount(fMatrices)) > 0) {
384 writeTagSize(buffer, PICT_MATRIX_BUFFER_TAG, n);
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000385 for (i = 0; i < n; i++) {
386 buffer.writeMatrix((*fMatrices)[i]);
387 }
388
reed@android.com8a1c16f2008-12-17 15:59:43 +0000389 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000390
reed@google.comf4cc1872012-07-23 15:04:45 +0000391 if ((n = SafeCount(fPaints)) > 0) {
392 writeTagSize(buffer, PICT_PAINT_BUFFER_TAG, n);
393 for (i = 0; i < n; i++) {
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000394 buffer.writePaint((*fPaints)[i]);
reed@google.com67562092012-06-22 15:38:39 +0000395 }
396 }
skia.committer@gmail.coma27096b2012-08-30 14:38:00 +0000397
djsollen@google.comc9ab9872012-08-29 18:52:07 +0000398 if ((n = SafeCount(fPathHeap.get())) > 0) {
reed@google.comf4cc1872012-07-23 15:04:45 +0000399 writeTagSize(buffer, PICT_PATH_BUFFER_TAG, n);
400 fPathHeap->flatten(buffer);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000401 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000402
reed@google.comf4cc1872012-07-23 15:04:45 +0000403 if ((n = SafeCount(fRegions)) > 0) {
404 writeTagSize(buffer, PICT_REGION_BUFFER_TAG, n);
405 for (i = 0; i < n; i++) {
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000406 buffer.writeRegion((*fRegions)[i]);
reed@google.com67562092012-06-22 15:38:39 +0000407 }
408 }
409}
reed@google.com82065d62011-02-07 15:30:46 +0000410
scroggo@google.com5a7c6be2012-10-04 21:46:08 +0000411void SkPicturePlayback::serialize(SkWStream* stream,
scroggo@google.com32ef1312013-02-22 22:04:19 +0000412 SkPicture::EncodeBitmap encoder) const {
reed@google.comddf98a82012-07-21 20:31:09 +0000413 writeTagSize(stream, PICT_READER_TAG, fOpData->size());
414 stream->write(fOpData->bytes(), fOpData->size());
reed@google.com67562092012-06-22 15:38:39 +0000415
416 if (fPictureCount > 0) {
417 writeTagSize(stream, PICT_PICTURE_TAG, fPictureCount);
418 for (int i = 0; i < fPictureCount; i++) {
scroggo@google.comf8d7d272013-02-22 21:38:35 +0000419 fPictureRefs[i]->serialize(stream, encoder);
reed@google.com67562092012-06-22 15:38:39 +0000420 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000421 }
reed@google.com82065d62011-02-07 15:30:46 +0000422
reed@google.com67562092012-06-22 15:38:39 +0000423 // Write some of our data into a writebuffer, and then serialize that
424 // into our stream
425 {
426 SkRefCntSet typefaceSet;
427 SkFactorySet factSet;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000428
reed@google.com67562092012-06-22 15:38:39 +0000429 SkOrderedWriteBuffer buffer(1024);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000430
reed@google.com67562092012-06-22 15:38:39 +0000431 buffer.setFlags(SkFlattenableWriteBuffer::kCrossProcess_Flag);
432 buffer.setTypefaceRecorder(&typefaceSet);
433 buffer.setFactoryRecorder(&factSet);
scroggo@google.com5a7c6be2012-10-04 21:46:08 +0000434 buffer.setBitmapEncoder(encoder);
reed@google.com34342f62012-06-25 14:36:28 +0000435
reed@google.com67562092012-06-22 15:38:39 +0000436 this->flattenToBuffer(buffer);
437
438 // We have to write these to sets into the stream *before* we write
439 // the buffer, since parsing that buffer will require that we already
440 // have these sets available to use.
441 writeFactories(stream, factSet);
442 writeTypefaces(stream, typefaceSet);
443
444 writeTagSize(stream, PICT_BUFFER_SIZE_TAG, buffer.size());
445 buffer.writeToStream(stream);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000446 }
reed@google.com82065d62011-02-07 15:30:46 +0000447
reed@google.comed384952012-06-22 13:12:17 +0000448 stream->write32(PICT_EOF_TAG);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000449}
450
451///////////////////////////////////////////////////////////////////////////////
452
reed@google.com34342f62012-06-25 14:36:28 +0000453/**
454 * Return the corresponding SkFlattenableReadBuffer flags, given a set of
455 * SkPictInfo flags.
456 */
457static uint32_t pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags) {
458 static const struct {
459 uint32_t fSrc;
460 uint32_t fDst;
461 } gSD[] = {
462 { SkPictInfo::kCrossProcess_Flag, SkFlattenableReadBuffer::kCrossProcess_Flag },
463 { SkPictInfo::kScalarIsFloat_Flag, SkFlattenableReadBuffer::kScalarIsFloat_Flag },
464 { SkPictInfo::kPtrIs64Bit_Flag, SkFlattenableReadBuffer::kPtrIs64Bit_Flag },
465 };
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000466
reed@google.com34342f62012-06-25 14:36:28 +0000467 uint32_t rbMask = 0;
468 for (size_t i = 0; i < SK_ARRAY_COUNT(gSD); ++i) {
469 if (pictInfoFlags & gSD[i].fSrc) {
470 rbMask |= gSD[i].fDst;
471 }
472 }
473 return rbMask;
474}
475
scroggo@google.com12d588a2013-02-25 16:05:00 +0000476void SkPicturePlayback::parseStreamTag(SkStream* stream, const SkPictInfo& info, uint32_t tag,
scroggo@google.comf8d7d272013-02-22 21:38:35 +0000477 size_t size, SkPicture::InstallPixelRefProc proc) {
reed@google.com67562092012-06-22 15:38:39 +0000478 /*
479 * By the time we encounter BUFFER_SIZE_TAG, we need to have already seen
480 * its dependents: FACTORY_TAG and TYPEFACE_TAG. These two are not required
481 * but if they are present, they need to have been seen before the buffer.
482 *
483 * We assert that if/when we see either of these, that we have not yet seen
484 * the buffer tag, because if we have, then its too-late to deal with the
485 * factories or typefaces.
486 */
scroggo@google.comc4dc8312013-02-22 15:46:44 +0000487 SkDEBUGCODE(bool haveBuffer = false;)
reed@google.com67562092012-06-22 15:38:39 +0000488
489 switch (tag) {
490 case PICT_READER_TAG: {
491 void* storage = sk_malloc_throw(size);
492 stream->read(storage, size);
reed@google.comddf98a82012-07-21 20:31:09 +0000493 SkASSERT(NULL == fOpData);
494 fOpData = SkData::NewFromMalloc(storage, size);
reed@google.com67562092012-06-22 15:38:39 +0000495 } break;
496 case PICT_FACTORY_TAG: {
497 SkASSERT(!haveBuffer);
498 fFactoryPlayback = SkNEW_ARGS(SkFactoryPlayback, (size));
499 for (size_t i = 0; i < size; i++) {
500 SkString str;
501 int len = stream->readPackedUInt();
502 str.resize(len);
503 stream->read(str.writable_str(), len);
504 fFactoryPlayback->base()[i] = SkFlattenable::NameToFactory(str.c_str());
505 }
506 } break;
507 case PICT_TYPEFACE_TAG: {
508 SkASSERT(!haveBuffer);
509 fTFPlayback.setCount(size);
510 for (size_t i = 0; i < size; i++) {
reed@google.com73c0abc2013-04-22 13:47:40 +0000511 SkAutoTUnref<SkTypeface> tf(SkTypeface::Deserialize(stream));
512 if (!tf.get()) { // failed to deserialize
513 // fTFPlayback asserts it never has a null, so we plop in
514 // the default here.
515 tf.reset(SkTypeface::RefDefault());
516 }
517 fTFPlayback.set(i, tf);
reed@google.com67562092012-06-22 15:38:39 +0000518 }
519 } break;
520 case PICT_PICTURE_TAG: {
521 fPictureCount = size;
522 fPictureRefs = SkNEW_ARRAY(SkPicture*, fPictureCount);
scroggo@google.com12d588a2013-02-25 16:05:00 +0000523 bool success;
524 for (int i = 0; i < fPictureCount; i++) {
scroggo@google.comf8d7d272013-02-22 21:38:35 +0000525 fPictureRefs[i] = SkNEW_ARGS(SkPicture, (stream, &success, proc));
scroggo@google.com12d588a2013-02-25 16:05:00 +0000526 // Success can only be false if PICTURE_VERSION does not match
527 // (which should never happen from here, since a sub picture will
528 // have the same PICTURE_VERSION as its parent) or if stream->read
529 // returns 0. In the latter case, we have a bug when writing the
530 // picture to begin with, which will be alerted to here.
531 SkASSERT(success);
reed@google.com67562092012-06-22 15:38:39 +0000532 }
533 } break;
534 case PICT_BUFFER_SIZE_TAG: {
535 SkAutoMalloc storage(size);
536 stream->read(storage.get(), size);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000537
reed@google.com67562092012-06-22 15:38:39 +0000538 SkOrderedReadBuffer buffer(storage.get(), size);
reed@google.com34342f62012-06-25 14:36:28 +0000539 buffer.setFlags(pictInfoFlagsToReadBufferFlags(info.fFlags));
540
reed@google.com67562092012-06-22 15:38:39 +0000541 fFactoryPlayback->setupBuffer(buffer);
542 fTFPlayback.setupBuffer(buffer);
scroggo@google.comf8d7d272013-02-22 21:38:35 +0000543 buffer.setBitmapDecoder(proc);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000544
reed@google.com67562092012-06-22 15:38:39 +0000545 while (!buffer.eof()) {
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000546 tag = buffer.readUInt();
547 size = buffer.readUInt();
scroggo@google.com12d588a2013-02-25 16:05:00 +0000548 this->parseBufferTag(buffer, tag, size);
reed@google.com67562092012-06-22 15:38:39 +0000549 }
scroggo@google.comc4dc8312013-02-22 15:46:44 +0000550 SkDEBUGCODE(haveBuffer = true;)
reed@google.com67562092012-06-22 15:38:39 +0000551 } break;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000552 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000553}
554
scroggo@google.com12d588a2013-02-25 16:05:00 +0000555void SkPicturePlayback::parseBufferTag(SkOrderedReadBuffer& buffer,
reed@google.com67562092012-06-22 15:38:39 +0000556 uint32_t tag, size_t size) {
557 switch (tag) {
558 case PICT_BITMAP_BUFFER_TAG: {
reed@google.comf4cc1872012-07-23 15:04:45 +0000559 fBitmaps = SkTRefArray<SkBitmap>::Create(size);
560 for (size_t i = 0; i < size; ++i) {
reed@google.comc52295f2012-12-07 15:53:49 +0000561 SkBitmap* bm = &fBitmaps->writableAt(i);
562 buffer.readBitmap(bm);
563 bm->setImmutable();
reed@google.com67562092012-06-22 15:38:39 +0000564 }
565 } break;
566 case PICT_MATRIX_BUFFER_TAG:
reed@google.comf4cc1872012-07-23 15:04:45 +0000567 fMatrices = SkTRefArray<SkMatrix>::Create(size);
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000568 for (size_t i = 0; i < size; ++i) {
569 buffer.readMatrix(&fMatrices->writableAt(i));
570 }
reed@google.com67562092012-06-22 15:38:39 +0000571 break;
572 case PICT_PAINT_BUFFER_TAG: {
reed@google.comf4cc1872012-07-23 15:04:45 +0000573 fPaints = SkTRefArray<SkPaint>::Create(size);
574 for (size_t i = 0; i < size; ++i) {
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000575 buffer.readPaint(&fPaints->writableAt(i));
reed@google.com67562092012-06-22 15:38:39 +0000576 }
577 } break;
578 case PICT_PATH_BUFFER_TAG:
579 if (size > 0) {
djsollen@google.comc9ab9872012-08-29 18:52:07 +0000580 fPathHeap.reset(SkNEW_ARGS(SkPathHeap, (buffer)));
reed@google.com67562092012-06-22 15:38:39 +0000581 }
582 break;
583 case PICT_REGION_BUFFER_TAG: {
reed@google.comf4cc1872012-07-23 15:04:45 +0000584 fRegions = SkTRefArray<SkRegion>::Create(size);
585 for (size_t i = 0; i < size; ++i) {
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000586 buffer.readRegion(&fRegions->writableAt(i));
reed@google.com67562092012-06-22 15:38:39 +0000587 }
588 } break;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000589 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000590}
591
scroggo@google.com12d588a2013-02-25 16:05:00 +0000592SkPicturePlayback::SkPicturePlayback(SkStream* stream, const SkPictInfo& info,
scroggo@google.comf8d7d272013-02-22 21:38:35 +0000593 SkPicture::InstallPixelRefProc proc) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000594 this->init();
595
reed@google.com67562092012-06-22 15:38:39 +0000596 for (;;) {
597 uint32_t tag = stream->readU32();
598 if (PICT_EOF_TAG == tag) {
599 break;
600 }
reed@google.com82065d62011-02-07 15:30:46 +0000601
reed@google.comed384952012-06-22 13:12:17 +0000602 uint32_t size = stream->readU32();
scroggo@google.com12d588a2013-02-25 16:05:00 +0000603 this->parseStreamTag(stream, info, tag, size, proc);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000604 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000605}
606
607///////////////////////////////////////////////////////////////////////////////
608///////////////////////////////////////////////////////////////////////////////
609
reed@android.comae814c82009-02-13 14:56:09 +0000610#ifdef SPEW_CLIP_SKIPPING
611struct SkipClipRec {
612 int fCount;
613 size_t fSize;
reed@google.com82065d62011-02-07 15:30:46 +0000614
reed@android.comae814c82009-02-13 14:56:09 +0000615 SkipClipRec() {
616 fCount = 0;
617 fSize = 0;
618 }
reed@google.com82065d62011-02-07 15:30:46 +0000619
reed@android.comae814c82009-02-13 14:56:09 +0000620 void recordSkip(size_t bytes) {
621 fCount += 1;
622 fSize += bytes;
623 }
624};
625#endif
626
robertphillips@google.com3f713722013-01-17 14:39:20 +0000627#ifdef SK_DEVELOPER
robertphillips@google.com5f971142012-12-07 20:48:56 +0000628size_t SkPicturePlayback::preDraw(size_t offset, int type) {
629 return 0;
robertphillips@google.com6f6dfb42012-11-13 18:28:06 +0000630}
631
632void SkPicturePlayback::postDraw(size_t offset) {
633}
634#endif
635
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000636/*
robertphillips@google.come4ce5b82013-02-15 17:19:15 +0000637 * Read the next op code and chunk size from 'reader'. The returned size
skia.committer@gmail.comce8343d2013-02-16 07:01:31 +0000638 * is the entire size of the chunk (including the opcode). Thus, the
robertphillips@google.come4ce5b82013-02-15 17:19:15 +0000639 * offset just prior to calling read_op_and_size + 'size' is the offset
skia.committer@gmail.comce8343d2013-02-16 07:01:31 +0000640 * to the next chunk's op code. This also means that the size of a chunk
robertphillips@google.come4ce5b82013-02-15 17:19:15 +0000641 * with no arguments (just an opcode) will be 4.
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000642 */
643static DrawType read_op_and_size(SkReader32* reader, uint32_t* size) {
644 uint32_t temp = reader->readInt();
645 uint32_t op;
646 if (((uint8_t) temp) == temp) {
647 // old skp file - no size information
648 op = temp;
649 *size = 0;
650 } else {
651 UNPACK_8_24(temp, op, *size);
652 if (MASK_24 == *size) {
653 *size = reader->readInt();
654 }
655 }
656 return (DrawType) op;
657}
658
reed@android.com8a1c16f2008-12-17 15:59:43 +0000659void SkPicturePlayback::draw(SkCanvas& canvas) {
660#ifdef ENABLE_TIME_DRAW
661 SkAutoTime at("SkPicture::draw", 50);
662#endif
reed@google.com82065d62011-02-07 15:30:46 +0000663
reed@android.comae814c82009-02-13 14:56:09 +0000664#ifdef SPEW_CLIP_SKIPPING
reed@google.com4ed0fb72012-12-12 20:48:18 +0000665 SkipClipRec skipRect, skipRRect, skipRegion, skipPath;
reed@android.comae814c82009-02-13 14:56:09 +0000666#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000667
djsollen@google.com56c69772011-11-08 19:00:26 +0000668#ifdef SK_BUILD_FOR_ANDROID
djsollen@google.comf5dbe2f2011-04-15 13:41:26 +0000669 SkAutoMutexAcquire autoMutex(fDrawMutex);
670#endif
671
robertphillips@google.com5f971142012-12-07 20:48:56 +0000672 // kDrawComplete will be the signal that we have reached the end of
673 // the command stream
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000674 static const uint32_t kDrawComplete = SK_MaxU32;
robertphillips@google.com5f971142012-12-07 20:48:56 +0000675
reed@google.comddf98a82012-07-21 20:31:09 +0000676 SkReader32 reader(fOpData->bytes(), fOpData->size());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000677 TextContainer text;
rileya@google.com8515e792012-09-13 21:41:51 +0000678 SkTDArray<void*> results;
679
rileya@google.com1c6307e2012-09-14 15:52:47 +0000680 if (NULL != fStateTree && NULL != fBoundingHierarchy) {
rileya@google.com8515e792012-09-13 21:41:51 +0000681 SkRect clipBounds;
682 if (canvas.getClipBounds(&clipBounds)) {
683 SkIRect query;
684 clipBounds.roundOut(&query);
685 fBoundingHierarchy->search(query, &results);
rileya@google.com1c6307e2012-09-14 15:52:47 +0000686 if (results.count() == 0) {
687 return;
688 }
rileya@google.com8515e792012-09-13 21:41:51 +0000689 SkTQSort<SkPictureStateTree::Draw>(
skia.committer@gmail.com1d225f22012-09-14 02:01:10 +0000690 reinterpret_cast<SkPictureStateTree::Draw**>(results.begin()),
rileya@google.com8515e792012-09-13 21:41:51 +0000691 reinterpret_cast<SkPictureStateTree::Draw**>(results.end()-1));
692 }
693 }
694
695 SkPictureStateTree::Iterator it = (NULL == fStateTree) ?
696 SkPictureStateTree::Iterator() :
697 fStateTree->getIterator(results, &canvas);
698
699 if (it.isValid()) {
robertphillips@google.com5f971142012-12-07 20:48:56 +0000700 uint32_t skipTo = it.draw();
701 if (kDrawComplete == skipTo) {
rileya@google.com1c6307e2012-09-14 15:52:47 +0000702 return;
703 }
robertphillips@google.com5f971142012-12-07 20:48:56 +0000704 reader.setOffset(skipTo);
rileya@google.com8515e792012-09-13 21:41:51 +0000705 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000706
reed@google.comb4c28192012-09-05 23:14:07 +0000707 // Record this, so we can concat w/ it if we encounter a setMatrix()
708 SkMatrix initialMatrix = canvas.getTotalMatrix();
709
djsollen@google.comd9b0f482013-02-01 16:18:09 +0000710#ifdef SK_BUILD_FOR_ANDROID
711 fAbortCurrentPlayback = false;
712#endif
713
reed@google.comddf98a82012-07-21 20:31:09 +0000714 while (!reader.eof()) {
djsollen@google.comd9b0f482013-02-01 16:18:09 +0000715#ifdef SK_BUILD_FOR_ANDROID
716 if (fAbortCurrentPlayback) {
717 return;
718 }
719#endif
720
robertphillips@google.com6f6dfb42012-11-13 18:28:06 +0000721 size_t curOffset = reader.offset();
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000722 uint32_t size;
723 DrawType op = read_op_and_size(&reader, &size);
commit-bot@chromium.org4b32bd52013-03-15 15:06:03 +0000724 size_t skipTo = 0;
725#ifdef SK_DEVELOPER
726 // TODO: once chunk sizes are in all .skps just use
727 // "curOffset + size"
728 skipTo = this->preDraw(curOffset, op);
729#endif
730 if (0 == skipTo && NOOP == op) {
robertphillips@google.come4ce5b82013-02-15 17:19:15 +0000731 // NOOPs are to be ignored - do not propagate them any further
commit-bot@chromium.org4b32bd52013-03-15 15:06:03 +0000732 skipTo = curOffset + size;
robertphillips@google.come4ce5b82013-02-15 17:19:15 +0000733 }
734
robertphillips@google.com5f971142012-12-07 20:48:56 +0000735 if (0 != skipTo) {
commit-bot@chromium.org4b32bd52013-03-15 15:06:03 +0000736 if (it.isValid()) {
737 // If using a bounding box hierarchy, advance the state tree
738 // iterator until at or after skipTo
739 uint32_t adjustedSkipTo;
740 do {
741 adjustedSkipTo = it.draw();
742 } while (adjustedSkipTo < skipTo);
743 skipTo = adjustedSkipTo;
744 }
robertphillips@google.com5f971142012-12-07 20:48:56 +0000745 if (kDrawComplete == skipTo) {
746 break;
747 }
748 reader.setOffset(skipTo);
749 continue;
750 }
commit-bot@chromium.org4b32bd52013-03-15 15:06:03 +0000751
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000752 switch (op) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000753 case CLIP_PATH: {
reed@google.comddf98a82012-07-21 20:31:09 +0000754 const SkPath& path = getPath(reader);
755 uint32_t packed = reader.readInt();
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000756 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
reed@google.com83ab4952011-11-11 21:34:54 +0000757 bool doAA = ClipParams_unpackDoAA(packed);
reed@google.comddf98a82012-07-21 20:31:09 +0000758 size_t offsetToRestore = reader.readInt();
junov@chromium.org9fa4d0c2012-07-09 20:53:37 +0000759 SkASSERT(!offsetToRestore || \
reed@google.comddf98a82012-07-21 20:31:09 +0000760 offsetToRestore >= reader.offset());
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000761 if (!canvas.clipPath(path, regionOp, doAA) && offsetToRestore) {
reed@android.comae814c82009-02-13 14:56:09 +0000762#ifdef SPEW_CLIP_SKIPPING
reed@google.comddf98a82012-07-21 20:31:09 +0000763 skipPath.recordSkip(offsetToRestore - reader.offset());
reed@android.comae814c82009-02-13 14:56:09 +0000764#endif
reed@google.comddf98a82012-07-21 20:31:09 +0000765 reader.setOffset(offsetToRestore);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000766 }
767 } break;
768 case CLIP_REGION: {
reed@google.comddf98a82012-07-21 20:31:09 +0000769 const SkRegion& region = getRegion(reader);
770 uint32_t packed = reader.readInt();
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000771 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
reed@google.comddf98a82012-07-21 20:31:09 +0000772 size_t offsetToRestore = reader.readInt();
junov@chromium.org9fa4d0c2012-07-09 20:53:37 +0000773 SkASSERT(!offsetToRestore || \
reed@google.comddf98a82012-07-21 20:31:09 +0000774 offsetToRestore >= reader.offset());
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000775 if (!canvas.clipRegion(region, regionOp) && offsetToRestore) {
reed@android.comae814c82009-02-13 14:56:09 +0000776#ifdef SPEW_CLIP_SKIPPING
reed@google.comddf98a82012-07-21 20:31:09 +0000777 skipRegion.recordSkip(offsetToRestore - reader.offset());
reed@android.comae814c82009-02-13 14:56:09 +0000778#endif
reed@google.comddf98a82012-07-21 20:31:09 +0000779 reader.setOffset(offsetToRestore);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000780 }
781 } break;
782 case CLIP_RECT: {
reed@google.comddf98a82012-07-21 20:31:09 +0000783 const SkRect& rect = reader.skipT<SkRect>();
784 uint32_t packed = reader.readInt();
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000785 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
reed@google.com83ab4952011-11-11 21:34:54 +0000786 bool doAA = ClipParams_unpackDoAA(packed);
reed@google.comddf98a82012-07-21 20:31:09 +0000787 size_t offsetToRestore = reader.readInt();
junov@chromium.org9fa4d0c2012-07-09 20:53:37 +0000788 SkASSERT(!offsetToRestore || \
reed@google.com4ed0fb72012-12-12 20:48:18 +0000789 offsetToRestore >= reader.offset());
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000790 if (!canvas.clipRect(rect, regionOp, doAA) && offsetToRestore) {
reed@android.comae814c82009-02-13 14:56:09 +0000791#ifdef SPEW_CLIP_SKIPPING
reed@google.comddf98a82012-07-21 20:31:09 +0000792 skipRect.recordSkip(offsetToRestore - reader.offset());
reed@android.comae814c82009-02-13 14:56:09 +0000793#endif
reed@google.comddf98a82012-07-21 20:31:09 +0000794 reader.setOffset(offsetToRestore);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000795 }
796 } break;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000797 case CLIP_RRECT: {
798 SkRRect rrect;
799 reader.readRRect(&rrect);
800 uint32_t packed = reader.readInt();
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000801 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000802 bool doAA = ClipParams_unpackDoAA(packed);
803 size_t offsetToRestore = reader.readInt();
804 SkASSERT(!offsetToRestore || \
805 offsetToRestore >= reader.offset());
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000806 if (!canvas.clipRRect(rrect, regionOp, doAA) && offsetToRestore) {
reed@google.com4ed0fb72012-12-12 20:48:18 +0000807#ifdef SPEW_CLIP_SKIPPING
808 skipRRect.recordSkip(offsetToRestore - reader.offset());
809#endif
810 reader.setOffset(offsetToRestore);
811 }
812 } break;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000813 case CONCAT:
reed@google.comddf98a82012-07-21 20:31:09 +0000814 canvas.concat(*getMatrix(reader));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000815 break;
816 case DRAW_BITMAP: {
reed@google.comddf98a82012-07-21 20:31:09 +0000817 const SkPaint* paint = getPaint(reader);
818 const SkBitmap& bitmap = getBitmap(reader);
819 const SkPoint& loc = reader.skipT<SkPoint>();
reed@google.coma5adf532011-09-07 13:52:17 +0000820 canvas.drawBitmap(bitmap, loc.fX, loc.fY, paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000821 } break;
reed@google.com71121732012-09-18 15:14:33 +0000822 case DRAW_BITMAP_RECT_TO_RECT: {
reed@google.comddf98a82012-07-21 20:31:09 +0000823 const SkPaint* paint = getPaint(reader);
824 const SkBitmap& bitmap = getBitmap(reader);
reed@google.com71121732012-09-18 15:14:33 +0000825 const SkRect* src = this->getRectPtr(reader); // may be null
reed@google.comddf98a82012-07-21 20:31:09 +0000826 const SkRect& dst = reader.skipT<SkRect>(); // required
reed@google.com71121732012-09-18 15:14:33 +0000827 canvas.drawBitmapRectToRect(bitmap, src, dst, paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000828 } break;
829 case DRAW_BITMAP_MATRIX: {
reed@google.comddf98a82012-07-21 20:31:09 +0000830 const SkPaint* paint = getPaint(reader);
831 const SkBitmap& bitmap = getBitmap(reader);
832 const SkMatrix* matrix = getMatrix(reader);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000833 canvas.drawBitmapMatrix(bitmap, *matrix, paint);
834 } break;
reed@google.comf0b5e112011-09-07 11:57:34 +0000835 case DRAW_BITMAP_NINE: {
reed@google.comddf98a82012-07-21 20:31:09 +0000836 const SkPaint* paint = getPaint(reader);
837 const SkBitmap& bitmap = getBitmap(reader);
838 const SkIRect& src = reader.skipT<SkIRect>();
839 const SkRect& dst = reader.skipT<SkRect>();
reed@google.coma5adf532011-09-07 13:52:17 +0000840 canvas.drawBitmapNine(bitmap, src, dst, paint);
reed@google.comf0b5e112011-09-07 11:57:34 +0000841 } break;
reed@google.com2a981812011-04-14 18:59:28 +0000842 case DRAW_CLEAR:
reed@google.comddf98a82012-07-21 20:31:09 +0000843 canvas.clear(reader.readInt());
reed@google.com2a981812011-04-14 18:59:28 +0000844 break;
reed@android.comcb608442009-12-04 21:32:27 +0000845 case DRAW_DATA: {
reed@google.comddf98a82012-07-21 20:31:09 +0000846 size_t length = reader.readInt();
847 canvas.drawData(reader.skip(length), length);
reed@android.comcb608442009-12-04 21:32:27 +0000848 // skip handles padding the read out to a multiple of 4
849 } break;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000850 case DRAW_OVAL: {
851 const SkPaint& paint = *getPaint(reader);
852 canvas.drawOval(reader.skipT<SkRect>(), paint);
853 } break;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000854 case DRAW_PAINT:
reed@google.comddf98a82012-07-21 20:31:09 +0000855 canvas.drawPaint(*getPaint(reader));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000856 break;
857 case DRAW_PATH: {
reed@google.comddf98a82012-07-21 20:31:09 +0000858 const SkPaint& paint = *getPaint(reader);
859 canvas.drawPath(getPath(reader), paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000860 } break;
861 case DRAW_PICTURE:
reed@google.comddf98a82012-07-21 20:31:09 +0000862 canvas.drawPicture(getPicture(reader));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000863 break;
864 case DRAW_POINTS: {
reed@google.comddf98a82012-07-21 20:31:09 +0000865 const SkPaint& paint = *getPaint(reader);
866 SkCanvas::PointMode mode = (SkCanvas::PointMode)reader.readInt();
867 size_t count = reader.readInt();
868 const SkPoint* pts = (const SkPoint*)reader.skip(sizeof(SkPoint) * count);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000869 canvas.drawPoints(mode, count, pts, paint);
870 } break;
871 case DRAW_POS_TEXT: {
reed@google.comddf98a82012-07-21 20:31:09 +0000872 const SkPaint& paint = *getPaint(reader);
873 getText(reader, &text);
874 size_t points = reader.readInt();
875 const SkPoint* pos = (const SkPoint*)reader.skip(points * sizeof(SkPoint));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000876 canvas.drawPosText(text.text(), text.length(), pos, paint);
877 } break;
reed@google.com9efd9a02012-01-30 15:41:43 +0000878 case DRAW_POS_TEXT_TOP_BOTTOM: {
reed@google.comddf98a82012-07-21 20:31:09 +0000879 const SkPaint& paint = *getPaint(reader);
880 getText(reader, &text);
881 size_t points = reader.readInt();
882 const SkPoint* pos = (const SkPoint*)reader.skip(points * sizeof(SkPoint));
883 const SkScalar top = reader.readScalar();
884 const SkScalar bottom = reader.readScalar();
reed@google.com3b3e8952012-08-16 20:53:31 +0000885 if (!canvas.quickRejectY(top, bottom)) {
reed@google.com9efd9a02012-01-30 15:41:43 +0000886 canvas.drawPosText(text.text(), text.length(), pos, paint);
887 }
888 } break;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000889 case DRAW_POS_TEXT_H: {
reed@google.comddf98a82012-07-21 20:31:09 +0000890 const SkPaint& paint = *getPaint(reader);
891 getText(reader, &text);
892 size_t xCount = reader.readInt();
893 const SkScalar constY = reader.readScalar();
894 const SkScalar* xpos = (const SkScalar*)reader.skip(xCount * sizeof(SkScalar));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000895 canvas.drawPosTextH(text.text(), text.length(), xpos, constY,
896 paint);
897 } break;
898 case DRAW_POS_TEXT_H_TOP_BOTTOM: {
reed@google.comddf98a82012-07-21 20:31:09 +0000899 const SkPaint& paint = *getPaint(reader);
900 getText(reader, &text);
901 size_t xCount = reader.readInt();
902 const SkScalar* xpos = (const SkScalar*)reader.skip((3 + xCount) * sizeof(SkScalar));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000903 const SkScalar top = *xpos++;
904 const SkScalar bottom = *xpos++;
905 const SkScalar constY = *xpos++;
reed@google.com3b3e8952012-08-16 20:53:31 +0000906 if (!canvas.quickRejectY(top, bottom)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000907 canvas.drawPosTextH(text.text(), text.length(), xpos,
908 constY, paint);
909 }
910 } break;
911 case DRAW_RECT: {
reed@google.comddf98a82012-07-21 20:31:09 +0000912 const SkPaint& paint = *getPaint(reader);
913 canvas.drawRect(reader.skipT<SkRect>(), paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000914 } break;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000915 case DRAW_RRECT: {
916 const SkPaint& paint = *getPaint(reader);
917 SkRRect rrect;
918 canvas.drawRRect(*reader.readRRect(&rrect), paint);
919 } break;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000920 case DRAW_SPRITE: {
reed@google.comddf98a82012-07-21 20:31:09 +0000921 const SkPaint* paint = getPaint(reader);
922 const SkBitmap& bitmap = getBitmap(reader);
923 int left = reader.readInt();
924 int top = reader.readInt();
reed@google.com82065d62011-02-07 15:30:46 +0000925 canvas.drawSprite(bitmap, left, top, paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000926 } break;
927 case DRAW_TEXT: {
reed@google.comddf98a82012-07-21 20:31:09 +0000928 const SkPaint& paint = *getPaint(reader);
929 getText(reader, &text);
930 SkScalar x = reader.readScalar();
931 SkScalar y = reader.readScalar();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000932 canvas.drawText(text.text(), text.length(), x, y, paint);
933 } break;
934 case DRAW_TEXT_TOP_BOTTOM: {
reed@google.comddf98a82012-07-21 20:31:09 +0000935 const SkPaint& paint = *getPaint(reader);
936 getText(reader, &text);
937 const SkScalar* ptr = (const SkScalar*)reader.skip(4 * sizeof(SkScalar));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000938 // ptr[0] == x
939 // ptr[1] == y
940 // ptr[2] == top
941 // ptr[3] == bottom
reed@google.com3b3e8952012-08-16 20:53:31 +0000942 if (!canvas.quickRejectY(ptr[2], ptr[3])) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000943 canvas.drawText(text.text(), text.length(), ptr[0], ptr[1],
944 paint);
945 }
946 } break;
947 case DRAW_TEXT_ON_PATH: {
reed@google.comddf98a82012-07-21 20:31:09 +0000948 const SkPaint& paint = *getPaint(reader);
949 getText(reader, &text);
950 const SkPath& path = getPath(reader);
951 const SkMatrix* matrix = getMatrix(reader);
reed@google.com82065d62011-02-07 15:30:46 +0000952 canvas.drawTextOnPath(text.text(), text.length(), path,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000953 matrix, paint);
954 } break;
955 case DRAW_VERTICES: {
reed@google.comddf98a82012-07-21 20:31:09 +0000956 const SkPaint& paint = *getPaint(reader);
957 DrawVertexFlags flags = (DrawVertexFlags)reader.readInt();
958 SkCanvas::VertexMode vmode = (SkCanvas::VertexMode)reader.readInt();
959 int vCount = reader.readInt();
960 const SkPoint* verts = (const SkPoint*)reader.skip(
reed@android.com8a1c16f2008-12-17 15:59:43 +0000961 vCount * sizeof(SkPoint));
962 const SkPoint* texs = NULL;
963 const SkColor* colors = NULL;
964 const uint16_t* indices = NULL;
965 int iCount = 0;
966 if (flags & DRAW_VERTICES_HAS_TEXS) {
reed@google.comddf98a82012-07-21 20:31:09 +0000967 texs = (const SkPoint*)reader.skip(
reed@android.com8a1c16f2008-12-17 15:59:43 +0000968 vCount * sizeof(SkPoint));
969 }
970 if (flags & DRAW_VERTICES_HAS_COLORS) {
reed@google.comddf98a82012-07-21 20:31:09 +0000971 colors = (const SkColor*)reader.skip(
reed@android.com8a1c16f2008-12-17 15:59:43 +0000972 vCount * sizeof(SkColor));
973 }
974 if (flags & DRAW_VERTICES_HAS_INDICES) {
reed@google.comddf98a82012-07-21 20:31:09 +0000975 iCount = reader.readInt();
976 indices = (const uint16_t*)reader.skip(
reed@android.com8a1c16f2008-12-17 15:59:43 +0000977 iCount * sizeof(uint16_t));
978 }
979 canvas.drawVertices(vmode, vCount, verts, texs, colors, NULL,
980 indices, iCount, paint);
981 } break;
982 case RESTORE:
983 canvas.restore();
984 break;
985 case ROTATE:
reed@google.comddf98a82012-07-21 20:31:09 +0000986 canvas.rotate(reader.readScalar());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000987 break;
988 case SAVE:
reed@google.comddf98a82012-07-21 20:31:09 +0000989 canvas.save((SkCanvas::SaveFlags) reader.readInt());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000990 break;
991 case SAVE_LAYER: {
reed@google.comddf98a82012-07-21 20:31:09 +0000992 const SkRect* boundsPtr = getRectPtr(reader);
993 const SkPaint* paint = getPaint(reader);
994 canvas.saveLayer(boundsPtr, paint, (SkCanvas::SaveFlags) reader.readInt());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000995 } break;
996 case SCALE: {
reed@google.comddf98a82012-07-21 20:31:09 +0000997 SkScalar sx = reader.readScalar();
998 SkScalar sy = reader.readScalar();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000999 canvas.scale(sx, sy);
1000 } break;
reed@google.comb4c28192012-09-05 23:14:07 +00001001 case SET_MATRIX: {
1002 SkMatrix matrix;
1003 matrix.setConcat(initialMatrix, *getMatrix(reader));
1004 canvas.setMatrix(matrix);
1005 } break;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001006 case SKEW: {
reed@google.comddf98a82012-07-21 20:31:09 +00001007 SkScalar sx = reader.readScalar();
1008 SkScalar sy = reader.readScalar();
reed@android.com8a1c16f2008-12-17 15:59:43 +00001009 canvas.skew(sx, sy);
1010 } break;
1011 case TRANSLATE: {
reed@google.comddf98a82012-07-21 20:31:09 +00001012 SkScalar dx = reader.readScalar();
1013 SkScalar dy = reader.readScalar();
reed@android.com8a1c16f2008-12-17 15:59:43 +00001014 canvas.translate(dx, dy);
1015 } break;
1016 default:
1017 SkASSERT(0);
1018 }
rileya@google.com8515e792012-09-13 21:41:51 +00001019
robertphillips@google.com3f713722013-01-17 14:39:20 +00001020#ifdef SK_DEVELOPER
robertphillips@google.com6f6dfb42012-11-13 18:28:06 +00001021 this->postDraw(curOffset);
1022#endif
1023
rileya@google.com8515e792012-09-13 21:41:51 +00001024 if (it.isValid()) {
robertphillips@google.com5f971142012-12-07 20:48:56 +00001025 uint32_t skipTo = it.draw();
1026 if (kDrawComplete == skipTo) {
rileya@google.com1c6307e2012-09-14 15:52:47 +00001027 break;
1028 }
robertphillips@google.com5f971142012-12-07 20:48:56 +00001029 reader.setOffset(skipTo);
rileya@google.com8515e792012-09-13 21:41:51 +00001030 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001031 }
reed@google.com82065d62011-02-07 15:30:46 +00001032
reed@android.comae814c82009-02-13 14:56:09 +00001033#ifdef SPEW_CLIP_SKIPPING
1034 {
reed@google.com4ed0fb72012-12-12 20:48:18 +00001035 size_t size = skipRect.fSize + skipRRect.fSize + skipPath.fSize + skipRegion.fSize;
1036 SkDebugf("--- Clip skips %d%% rect:%d rrect:%d path:%d rgn:%d\n",
1037 size * 100 / reader.offset(), skipRect.fCount, skipRRect.fCount,
1038 skipPath.fCount, skipRegion.fCount);
reed@android.comae814c82009-02-13 14:56:09 +00001039 }
1040#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +00001041// this->dumpSize();
1042}
1043
reed@android.com8a1c16f2008-12-17 15:59:43 +00001044///////////////////////////////////////////////////////////////////////////////
1045
reed@android.com8a1c16f2008-12-17 15:59:43 +00001046#ifdef SK_DEBUG_SIZE
reed@google.com82065d62011-02-07 15:30:46 +00001047int SkPicturePlayback::size(size_t* sizePtr) {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001048 int objects = bitmaps(sizePtr);
1049 objects += paints(sizePtr);
1050 objects += paths(sizePtr);
1051 objects += pictures(sizePtr);
1052 objects += regions(sizePtr);
reed@google.comddf98a82012-07-21 20:31:09 +00001053 *sizePtr = fOpData.size();
reed@google.com82065d62011-02-07 15:30:46 +00001054 return objects;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001055}
1056
1057int SkPicturePlayback::bitmaps(size_t* size) {
1058 size_t result = 0;
1059 for (int index = 0; index < fBitmapCount; index++) {
1060 // const SkBitmap& bitmap = fBitmaps[index];
1061 result += sizeof(SkBitmap); // bitmap->size();
1062 }
1063 *size = result;
1064 return fBitmapCount;
1065}
1066
1067int SkPicturePlayback::paints(size_t* size) {
1068 size_t result = 0;
1069 for (int index = 0; index < fPaintCount; index++) {
1070 // const SkPaint& paint = fPaints[index];
1071 result += sizeof(SkPaint); // paint->size();
1072 }
1073 *size = result;
1074 return fPaintCount;
1075}
1076
1077int SkPicturePlayback::paths(size_t* size) {
1078 size_t result = 0;
1079 for (int index = 0; index < fPathCount; index++) {
1080 const SkPath& path = fPaths[index];
1081 result += path.flatten(NULL);
1082 }
1083 *size = result;
1084 return fPathCount;
1085}
1086
1087int SkPicturePlayback::regions(size_t* size) {
1088 size_t result = 0;
1089 for (int index = 0; index < fRegionCount; index++) {
1090 // const SkRegion& region = fRegions[index];
1091 result += sizeof(SkRegion); // region->size();
1092 }
1093 *size = result;
1094 return fRegionCount;
1095}
1096#endif
1097
1098#ifdef SK_DEBUG_DUMP
1099void SkPicturePlayback::dumpBitmap(const SkBitmap& bitmap) const {
1100 char pBuffer[DUMP_BUFFER_SIZE];
1101 char* bufferPtr = pBuffer;
1102 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1103 "BitmapData bitmap%p = {", &bitmap);
1104 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1105 "{kWidth, %d}, ", bitmap.width());
1106 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1107 "{kHeight, %d}, ", bitmap.height());
1108 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1109 "{kRowBytes, %d}, ", bitmap.rowBytes());
1110// start here;
1111 SkDebugf("%s{0}};\n", pBuffer);
1112}
1113
1114void dumpMatrix(const SkMatrix& matrix) const {
1115 SkMatrix defaultMatrix;
1116 defaultMatrix.reset();
1117 char pBuffer[DUMP_BUFFER_SIZE];
1118 char* bufferPtr = pBuffer;
1119 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1120 "MatrixData matrix%p = {", &matrix);
1121 SkScalar scaleX = matrix.getScaleX();
1122 if (scaleX != defaultMatrix.getScaleX())
1123 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1124 "{kScaleX, %g}, ", SkScalarToFloat(scaleX));
1125 SkScalar scaleY = matrix.getScaleY();
1126 if (scaleY != defaultMatrix.getScaleY())
1127 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1128 "{kScaleY, %g}, ", SkScalarToFloat(scaleY));
1129 SkScalar skewX = matrix.getSkewX();
1130 if (skewX != defaultMatrix.getSkewX())
1131 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1132 "{kSkewX, %g}, ", SkScalarToFloat(skewX));
1133 SkScalar skewY = matrix.getSkewY();
1134 if (skewY != defaultMatrix.getSkewY())
1135 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1136 "{kSkewY, %g}, ", SkScalarToFloat(skewY));
1137 SkScalar translateX = matrix.getTranslateX();
1138 if (translateX != defaultMatrix.getTranslateX())
1139 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1140 "{kTranslateX, %g}, ", SkScalarToFloat(translateX));
1141 SkScalar translateY = matrix.getTranslateY();
1142 if (translateY != defaultMatrix.getTranslateY())
1143 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1144 "{kTranslateY, %g}, ", SkScalarToFloat(translateY));
1145 SkScalar perspX = matrix.getPerspX();
1146 if (perspX != defaultMatrix.getPerspX())
1147 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1148 "{kPerspX, %g}, ", SkFractToFloat(perspX));
1149 SkScalar perspY = matrix.getPerspY();
1150 if (perspY != defaultMatrix.getPerspY())
1151 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1152 "{kPerspY, %g}, ", SkFractToFloat(perspY));
1153 SkDebugf("%s{0}};\n", pBuffer);
1154}
1155
1156void dumpPaint(const SkPaint& paint) const {
1157 SkPaint defaultPaint;
1158 char pBuffer[DUMP_BUFFER_SIZE];
1159 char* bufferPtr = pBuffer;
1160 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1161 "PaintPointers paintPtrs%p = {", &paint);
1162 const SkTypeface* typeface = paint.getTypeface();
1163 if (typeface != defaultPaint.getTypeface())
1164 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1165 "{kTypeface, %p}, ", typeface);
1166 const SkPathEffect* pathEffect = paint.getPathEffect();
1167 if (pathEffect != defaultPaint.getPathEffect())
1168 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1169 "{kPathEffect, %p}, ", pathEffect);
1170 const SkShader* shader = paint.getShader();
1171 if (shader != defaultPaint.getShader())
1172 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1173 "{kShader, %p}, ", shader);
1174 const SkXfermode* xfermode = paint.getXfermode();
1175 if (xfermode != defaultPaint.getXfermode())
1176 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1177 "{kXfermode, %p}, ", xfermode);
1178 const SkMaskFilter* maskFilter = paint.getMaskFilter();
1179 if (maskFilter != defaultPaint.getMaskFilter())
1180 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1181 "{kMaskFilter, %p}, ", maskFilter);
1182 const SkColorFilter* colorFilter = paint.getColorFilter();
1183 if (colorFilter != defaultPaint.getColorFilter())
1184 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1185 "{kColorFilter, %p}, ", colorFilter);
1186 const SkRasterizer* rasterizer = paint.getRasterizer();
1187 if (rasterizer != defaultPaint.getRasterizer())
1188 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1189 "{kRasterizer, %p}, ", rasterizer);
1190 const SkDrawLooper* drawLooper = paint.getLooper();
1191 if (drawLooper != defaultPaint.getLooper())
1192 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1193 "{kDrawLooper, %p}, ", drawLooper);
1194 SkDebugf("%s{0}};\n", pBuffer);
1195 bufferPtr = pBuffer;
1196 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1197 "PaintScalars paintScalars%p = {", &paint);
1198 SkScalar textSize = paint.getTextSize();
1199 if (textSize != defaultPaint.getTextSize())
1200 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1201 "{kTextSize, %g}, ", SkScalarToFloat(textSize));
1202 SkScalar textScaleX = paint.getTextScaleX();
1203 if (textScaleX != defaultPaint.getTextScaleX())
1204 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1205 "{kTextScaleX, %g}, ", SkScalarToFloat(textScaleX));
1206 SkScalar textSkewX = paint.getTextSkewX();
1207 if (textSkewX != defaultPaint.getTextSkewX())
1208 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1209 "{kTextSkewX, %g}, ", SkScalarToFloat(textSkewX));
1210 SkScalar strokeWidth = paint.getStrokeWidth();
1211 if (strokeWidth != defaultPaint.getStrokeWidth())
1212 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1213 "{kStrokeWidth, %g}, ", SkScalarToFloat(strokeWidth));
1214 SkScalar strokeMiter = paint.getStrokeMiter();
1215 if (strokeMiter != defaultPaint.getStrokeMiter())
1216 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1217 "{kStrokeMiter, %g}, ", SkScalarToFloat(strokeMiter));
1218 SkDebugf("%s{0}};\n", pBuffer);
1219 bufferPtr = pBuffer;
1220 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1221 "PaintInts = paintInts%p = {", &paint);
1222 unsigned color = paint.getColor();
1223 if (color != defaultPaint.getColor())
1224 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1225 "{kColor, 0x%x}, ", color);
1226 unsigned flags = paint.getFlags();
1227 if (flags != defaultPaint.getFlags())
1228 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1229 "{kFlags, 0x%x}, ", flags);
1230 int align = paint.getTextAlign();
1231 if (align != defaultPaint.getTextAlign())
1232 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1233 "{kAlign, 0x%x}, ", align);
1234 int strokeCap = paint.getStrokeCap();
1235 if (strokeCap != defaultPaint.getStrokeCap())
1236 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1237 "{kStrokeCap, 0x%x}, ", strokeCap);
1238 int strokeJoin = paint.getStrokeJoin();
1239 if (strokeJoin != defaultPaint.getStrokeJoin())
1240 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1241 "{kAlign, 0x%x}, ", strokeJoin);
1242 int style = paint.getStyle();
1243 if (style != defaultPaint.getStyle())
1244 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1245 "{kStyle, 0x%x}, ", style);
1246 int textEncoding = paint.getTextEncoding();
1247 if (textEncoding != defaultPaint.getTextEncoding())
1248 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1249 "{kTextEncoding, 0x%x}, ", textEncoding);
1250 SkDebugf("%s{0}};\n", pBuffer);
1251
1252 SkDebugf("PaintData paint%p = {paintPtrs%p, paintScalars%p, paintInts%p};\n",
1253 &paint, &paint, &paint, &paint);
1254}
1255
1256void SkPicturePlayback::dumpPath(const SkPath& path) const {
1257 SkDebugf("path dump unimplemented\n");
1258}
1259
1260void SkPicturePlayback::dumpPicture(const SkPicture& picture) const {
1261 SkDebugf("picture dump unimplemented\n");
1262}
1263
1264void SkPicturePlayback::dumpRegion(const SkRegion& region) const {
1265 SkDebugf("region dump unimplemented\n");
1266}
1267
1268int SkPicturePlayback::dumpDrawType(char* bufferPtr, char* buffer, DrawType drawType) {
1269 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1270 "k%s, ", DrawTypeToString(drawType));
1271}
1272
1273int SkPicturePlayback::dumpInt(char* bufferPtr, char* buffer, char* name) {
1274 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1275 "%s:%d, ", name, getInt());
1276}
1277
1278int SkPicturePlayback::dumpRect(char* bufferPtr, char* buffer, char* name) {
1279 const SkRect* rect = fReader.skipRect();
1280 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
reed@google.com82065d62011-02-07 15:30:46 +00001281 "%s:{l:%g t:%g r:%g b:%g}, ", name, SkScalarToFloat(rect.fLeft),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001282 SkScalarToFloat(rect.fTop),
1283 SkScalarToFloat(rect.fRight), SkScalarToFloat(rect.fBottom));
1284}
1285
1286int SkPicturePlayback::dumpPoint(char* bufferPtr, char* buffer, char* name) {
1287 SkPoint pt;
1288 getPoint(&pt);
1289 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
reed@google.com82065d62011-02-07 15:30:46 +00001290 "%s:{x:%g y:%g}, ", name, SkScalarToFloat(pt.fX),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001291 SkScalarToFloat(pt.fY));
1292}
1293
1294void SkPicturePlayback::dumpPointArray(char** bufferPtrPtr, char* buffer, int count) {
1295 char* bufferPtr = *bufferPtrPtr;
1296 const SkPoint* pts = (const SkPoint*)fReadStream.getAtPos();
1297 fReadStream.skip(sizeof(SkPoint) * count);
1298 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1299 "count:%d {", count);
1300 for (int index = 0; index < count; index++)
1301 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
reed@google.com82065d62011-02-07 15:30:46 +00001302 "{x:%g y:%g}, ", SkScalarToFloat(pts[index].fX),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001303 SkScalarToFloat(pts[index].fY));
1304 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1305 "} ");
1306 *bufferPtrPtr = bufferPtr;
1307}
1308
1309int SkPicturePlayback::dumpPtr(char* bufferPtr, char* buffer, char* name, void* ptr) {
1310 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1311 "%s:%p, ", name, ptr);
1312}
1313
1314int SkPicturePlayback::dumpRectPtr(char* bufferPtr, char* buffer, char* name) {
1315 char result;
1316 fReadStream.read(&result, sizeof(result));
1317 if (result)
1318 return dumpRect(bufferPtr, buffer, name);
1319 else
1320 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1321 "%s:NULL, ", name);
1322}
1323
1324int SkPicturePlayback::dumpScalar(char* bufferPtr, char* buffer, char* name) {
1325 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1326 "%s:%d, ", name, getScalar());
1327}
1328
1329void SkPicturePlayback::dumpText(char** bufferPtrPtr, char* buffer) {
1330 char* bufferPtr = *bufferPtrPtr;
1331 int length = getInt();
1332 bufferPtr += dumpDrawType(bufferPtr, buffer);
1333 fReadStream.skipToAlign4();
1334 char* text = (char*) fReadStream.getAtPos();
1335 fReadStream.skip(length);
1336 bufferPtr += dumpInt(bufferPtr, buffer, "length");
1337 int limit = DUMP_BUFFER_SIZE - (bufferPtr - buffer) - 2;
1338 length >>= 1;
1339 if (limit > length)
1340 limit = length;
1341 if (limit > 0) {
1342 *bufferPtr++ = '"';
1343 for (int index = 0; index < limit; index++) {
1344 *bufferPtr++ = *(unsigned short*) text;
1345 text += sizeof(unsigned short);
1346 }
1347 *bufferPtr++ = '"';
1348 }
1349 *bufferPtrPtr = bufferPtr;
1350}
1351
1352#define DUMP_DRAWTYPE(drawType) \
1353 bufferPtr += dumpDrawType(bufferPtr, buffer, drawType)
1354
1355#define DUMP_INT(name) \
1356 bufferPtr += dumpInt(bufferPtr, buffer, #name)
1357
1358#define DUMP_RECT_PTR(name) \
1359 bufferPtr += dumpRectPtr(bufferPtr, buffer, #name)
1360
1361#define DUMP_POINT(name) \
1362 bufferPtr += dumpRect(bufferPtr, buffer, #name)
1363
1364#define DUMP_RECT(name) \
1365 bufferPtr += dumpRect(bufferPtr, buffer, #name)
1366
1367#define DUMP_POINT_ARRAY(count) \
1368 dumpPointArray(&bufferPtr, buffer, count)
1369
1370#define DUMP_PTR(name, ptr) \
1371 bufferPtr += dumpPtr(bufferPtr, buffer, #name, (void*) ptr)
1372
1373#define DUMP_SCALAR(name) \
1374 bufferPtr += dumpScalar(bufferPtr, buffer, #name)
1375
1376#define DUMP_TEXT() \
1377 dumpText(&bufferPtr, buffer)
1378
1379void SkPicturePlayback::dumpStream() {
1380 SkDebugf("RecordStream stream = {\n");
1381 DrawType drawType;
1382 TextContainer text;
1383 fReadStream.rewind();
1384 char buffer[DUMP_BUFFER_SIZE], * bufferPtr;
1385 while (fReadStream.read(&drawType, sizeof(drawType))) {
1386 bufferPtr = buffer;
1387 DUMP_DRAWTYPE(drawType);
1388 switch (drawType) {
1389 case CLIP_PATH: {
1390 DUMP_PTR(SkPath, &getPath());
1391 DUMP_INT(SkRegion::Op);
1392 DUMP_INT(offsetToRestore);
1393 } break;
1394 case CLIP_REGION: {
1395 DUMP_PTR(SkRegion, &getRegion());
1396 DUMP_INT(SkRegion::Op);
1397 DUMP_INT(offsetToRestore);
1398 } break;
1399 case CLIP_RECT: {
1400 DUMP_RECT(rect);
1401 DUMP_INT(SkRegion::Op);
1402 DUMP_INT(offsetToRestore);
1403 } break;
1404 case CONCAT:
1405 DUMP_PTR(SkMatrix, getMatrix());
1406 break;
1407 case DRAW_BITMAP: {
1408 DUMP_PTR(SkPaint, getPaint());
1409 DUMP_PTR(SkBitmap, &getBitmap());
1410 DUMP_SCALAR(left);
1411 DUMP_SCALAR(top);
1412 } break;
1413 case DRAW_PAINT:
1414 DUMP_PTR(SkPaint, getPaint());
1415 break;
1416 case DRAW_PATH: {
1417 DUMP_PTR(SkPaint, getPaint());
1418 DUMP_PTR(SkPath, &getPath());
1419 } break;
1420 case DRAW_PICTURE: {
1421 DUMP_PTR(SkPicture, &getPicture());
1422 } break;
1423 case DRAW_POINTS: {
1424 DUMP_PTR(SkPaint, getPaint());
1425 (void)getInt(); // PointMode
1426 size_t count = getInt();
1427 fReadStream.skipToAlign4();
1428 DUMP_POINT_ARRAY(count);
1429 } break;
1430 case DRAW_POS_TEXT: {
1431 DUMP_PTR(SkPaint, getPaint());
1432 DUMP_TEXT();
1433 size_t points = getInt();
1434 fReadStream.skipToAlign4();
1435 DUMP_POINT_ARRAY(points);
1436 } break;
1437 case DRAW_POS_TEXT_H: {
1438 DUMP_PTR(SkPaint, getPaint());
1439 DUMP_TEXT();
1440 size_t points = getInt();
1441 fReadStream.skipToAlign4();
1442 DUMP_SCALAR(top);
1443 DUMP_SCALAR(bottom);
1444 DUMP_SCALAR(constY);
1445 DUMP_POINT_ARRAY(points);
1446 } break;
1447 case DRAW_RECT: {
1448 DUMP_PTR(SkPaint, getPaint());
1449 DUMP_RECT(rect);
1450 } break;
1451 case DRAW_SPRITE: {
1452 DUMP_PTR(SkPaint, getPaint());
1453 DUMP_PTR(SkBitmap, &getBitmap());
1454 DUMP_SCALAR(left);
1455 DUMP_SCALAR(top);
1456 } break;
1457 case DRAW_TEXT: {
1458 DUMP_PTR(SkPaint, getPaint());
1459 DUMP_TEXT();
1460 DUMP_SCALAR(x);
1461 DUMP_SCALAR(y);
1462 } break;
1463 case DRAW_TEXT_ON_PATH: {
1464 DUMP_PTR(SkPaint, getPaint());
1465 DUMP_TEXT();
1466 DUMP_PTR(SkPath, &getPath());
1467 DUMP_PTR(SkMatrix, getMatrix());
1468 } break;
1469 case RESTORE:
1470 break;
1471 case ROTATE:
1472 DUMP_SCALAR(rotate);
1473 break;
1474 case SAVE:
1475 DUMP_INT(SkCanvas::SaveFlags);
1476 break;
1477 case SAVE_LAYER: {
1478 DUMP_RECT_PTR(layer);
1479 DUMP_PTR(SkPaint, getPaint());
1480 DUMP_INT(SkCanvas::SaveFlags);
1481 } break;
1482 case SCALE: {
1483 DUMP_SCALAR(sx);
1484 DUMP_SCALAR(sy);
1485 } break;
1486 case SKEW: {
1487 DUMP_SCALAR(sx);
1488 DUMP_SCALAR(sy);
1489 } break;
1490 case TRANSLATE: {
1491 DUMP_SCALAR(dx);
1492 DUMP_SCALAR(dy);
1493 } break;
1494 default:
1495 SkASSERT(0);
1496 }
1497 SkDebugf("%s\n", buffer);
1498 }
1499}
1500
1501void SkPicturePlayback::dump() const {
1502 char pBuffer[DUMP_BUFFER_SIZE];
1503 char* bufferPtr = pBuffer;
1504 int index;
1505 if (fBitmapCount > 0)
1506 SkDebugf("// bitmaps (%d)\n", fBitmapCount);
1507 for (index = 0; index < fBitmapCount; index++) {
1508 const SkBitmap& bitmap = fBitmaps[index];
1509 dumpBitmap(bitmap);
1510 }
1511 if (fBitmapCount > 0)
reed@google.com82065d62011-02-07 15:30:46 +00001512 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001513 "Bitmaps bitmaps = {");
1514 for (index = 0; index < fBitmapCount; index++)
reed@google.com82065d62011-02-07 15:30:46 +00001515 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001516 "bitmap%p, ", &fBitmaps[index]);
1517 if (fBitmapCount > 0)
1518 SkDebugf("%s0};\n", pBuffer);
1519
1520 if (fMatrixCount > 0)
1521 SkDebugf("// matrices (%d)\n", fMatrixCount);
1522 for (index = 0; index < fMatrixCount; index++) {
1523 const SkMatrix& matrix = fMatrices[index];
1524 dumpMatrix(matrix);
1525 }
1526 bufferPtr = pBuffer;
1527 if (fMatrixCount > 0)
reed@google.com82065d62011-02-07 15:30:46 +00001528 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001529 "Matrices matrices = {");
1530 for (index = 0; index < fMatrixCount; index++)
reed@google.com82065d62011-02-07 15:30:46 +00001531 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001532 "matrix%p, ", &fMatrices[index]);
1533 if (fMatrixCount > 0)
1534 SkDebugf("%s0};\n", pBuffer);
1535
1536 if (fPaintCount > 0)
1537 SkDebugf("// paints (%d)\n", fPaintCount);
1538 for (index = 0; index < fPaintCount; index++) {
1539 const SkPaint& paint = fPaints[index];
1540 dumpPaint(paint);
1541 }
1542 bufferPtr = pBuffer;
1543 if (fPaintCount > 0)
reed@google.com82065d62011-02-07 15:30:46 +00001544 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001545 "Paints paints = {");
1546 for (index = 0; index < fPaintCount; index++)
reed@google.com82065d62011-02-07 15:30:46 +00001547 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001548 "paint%p, ", &fPaints[index]);
1549 if (fPaintCount > 0)
1550 SkDebugf("%s0};\n", pBuffer);
1551
1552 for (index = 0; index < fPathCount; index++) {
1553 const SkPath& path = fPaths[index];
1554 dumpPath(path);
1555 }
1556 bufferPtr = pBuffer;
1557 if (fPathCount > 0)
reed@google.com82065d62011-02-07 15:30:46 +00001558 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001559 "Paths paths = {");
1560 for (index = 0; index < fPathCount; index++)
reed@google.com82065d62011-02-07 15:30:46 +00001561 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001562 "path%p, ", &fPaths[index]);
1563 if (fPathCount > 0)
1564 SkDebugf("%s0};\n", pBuffer);
1565
1566 for (index = 0; index < fPictureCount; index++) {
1567 dumpPicture(*fPictureRefs[index]);
1568 }
1569 bufferPtr = pBuffer;
1570 if (fPictureCount > 0)
reed@google.com82065d62011-02-07 15:30:46 +00001571 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001572 "Pictures pictures = {");
1573 for (index = 0; index < fPictureCount; index++)
reed@google.com82065d62011-02-07 15:30:46 +00001574 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001575 "picture%p, ", fPictureRefs[index]);
1576 if (fPictureCount > 0)
1577 SkDebugf("%s0};\n", pBuffer);
1578
1579 for (index = 0; index < fRegionCount; index++) {
1580 const SkRegion& region = fRegions[index];
1581 dumpRegion(region);
1582 }
1583 bufferPtr = pBuffer;
1584 if (fRegionCount > 0)
reed@google.com82065d62011-02-07 15:30:46 +00001585 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001586 "Regions regions = {");
1587 for (index = 0; index < fRegionCount; index++)
reed@google.com82065d62011-02-07 15:30:46 +00001588 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001589 "region%p, ", &fRegions[index]);
1590 if (fRegionCount > 0)
1591 SkDebugf("%s0};\n", pBuffer);
1592
1593 const_cast<SkPicturePlayback*>(this)->dumpStream();
1594}
1595
1596#endif