blob: f05aeaab9e920c0ada3bcadc3702e1d61d40730b [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>
14
reed@google.comf4cc1872012-07-23 15:04:45 +000015template <typename T> int SafeCount(const T* obj) {
16 return obj ? obj->count() : 0;
17}
18
reed@android.comae814c82009-02-13 14:56:09 +000019/* Define this to spew out a debug statement whenever we skip the remainder of
20 a save/restore block because a clip... command returned false (empty).
21 */
22#define SPEW_CLIP_SKIPPINGx
23
reed@android.com8a1c16f2008-12-17 15:59:43 +000024SkPicturePlayback::SkPicturePlayback() {
25 this->init();
26}
27
28SkPicturePlayback::SkPicturePlayback(const SkPictureRecord& record) {
29#ifdef SK_DEBUG_SIZE
reed@google.com82065d62011-02-07 15:30:46 +000030 size_t overallBytes, bitmapBytes, matricesBytes,
reed@android.com8a1c16f2008-12-17 15:59:43 +000031 paintBytes, pathBytes, pictureBytes, regionBytes;
32 int bitmaps = record.bitmaps(&bitmapBytes);
33 int matrices = record.matrices(&matricesBytes);
34 int paints = record.paints(&paintBytes);
35 int paths = record.paths(&pathBytes);
36 int pictures = record.pictures(&pictureBytes);
37 int regions = record.regions(&regionBytes);
38 SkDebugf("picture record mem used %zd (stream %zd) ", record.size(),
39 record.streamlen());
40 if (bitmaps != 0)
41 SkDebugf("bitmaps size %zd (bitmaps:%d) ", bitmapBytes, bitmaps);
42 if (matrices != 0)
43 SkDebugf("matrices size %zd (matrices:%d) ", matricesBytes, matrices);
44 if (paints != 0)
45 SkDebugf("paints size %zd (paints:%d) ", paintBytes, paints);
46 if (paths != 0)
47 SkDebugf("paths size %zd (paths:%d) ", pathBytes, paths);
48 if (pictures != 0)
49 SkDebugf("pictures size %zd (pictures:%d) ", pictureBytes, pictures);
50 if (regions != 0)
51 SkDebugf("regions size %zd (regions:%d) ", regionBytes, regions);
52 if (record.fPointWrites != 0)
53 SkDebugf("points size %zd (points:%d) ", record.fPointBytes, record.fPointWrites);
54 if (record.fRectWrites != 0)
55 SkDebugf("rects size %zd (rects:%d) ", record.fRectBytes, record.fRectWrites);
56 if (record.fTextWrites != 0)
57 SkDebugf("text size %zd (text strings:%d) ", record.fTextBytes, record.fTextWrites);
reed@google.com82065d62011-02-07 15:30:46 +000058
reed@android.com8a1c16f2008-12-17 15:59:43 +000059 SkDebugf("\n");
60#endif
61#ifdef SK_DEBUG_DUMP
62 record.dumpMatrices();
63 record.dumpPaints();
64#endif
65
66 record.validate();
67 const SkWriter32& writer = record.writeStream();
68 init();
69 if (writer.size() == 0)
70 return;
reed@google.com82065d62011-02-07 15:30:46 +000071
reed@android.com8a1c16f2008-12-17 15:59:43 +000072 {
73 size_t size = writer.size();
74 void* buffer = sk_malloc_throw(size);
75 writer.flatten(buffer);
reed@google.comddf98a82012-07-21 20:31:09 +000076 SkASSERT(!fOpData);
77 fOpData = SkData::NewFromMalloc(buffer, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +000078 }
reed@google.com82065d62011-02-07 15:30:46 +000079
reed@android.com8a1c16f2008-12-17 15:59:43 +000080 // copy over the refcnt dictionary to our reader
81 //
scroggo@google.com15543602012-08-02 18:49:49 +000082 record.fHeap.setupPlaybacks();
83 fBitmaps = record.getBitmaps().unflattenToArray();
84 fMatrices = record.getMatrices().unflattenToArray();
85 fPaints = record.getPaints().unflattenToArray();
86 fRegions = record.getRegions().unflattenToArray();
reed@android.com8a1c16f2008-12-17 15:59:43 +000087
88 fPathHeap = record.fPathHeap;
reed@google.com82065d62011-02-07 15:30:46 +000089 SkSafeRef(fPathHeap);
reed@android.com8a1c16f2008-12-17 15:59:43 +000090
91 const SkTDArray<SkPicture* >& pictures = record.getPictureRefs();
92 fPictureCount = pictures.count();
93 if (fPictureCount > 0) {
94 fPictureRefs = SkNEW_ARRAY(SkPicture*, fPictureCount);
95 for (int i = 0; i < fPictureCount; i++) {
96 fPictureRefs[i] = pictures[i];
97 fPictureRefs[i]->ref();
98 }
99 }
reed@google.com82065d62011-02-07 15:30:46 +0000100
reed@android.com8a1c16f2008-12-17 15:59:43 +0000101#ifdef SK_DEBUG_SIZE
102 int overall = fPlayback->size(&overallBytes);
103 bitmaps = fPlayback->bitmaps(&bitmapBytes);
104 paints = fPlayback->paints(&paintBytes);
105 paths = fPlayback->paths(&pathBytes);
106 pictures = fPlayback->pictures(&pictureBytes);
107 regions = fPlayback->regions(&regionBytes);
108 SkDebugf("playback size %zd (objects:%d) ", overallBytes, overall);
109 if (bitmaps != 0)
110 SkDebugf("bitmaps size %zd (bitmaps:%d) ", bitmapBytes, bitmaps);
111 if (paints != 0)
112 SkDebugf("paints size %zd (paints:%d) ", paintBytes, paints);
113 if (paths != 0)
114 SkDebugf("paths size %zd (paths:%d) ", pathBytes, paths);
115 if (pictures != 0)
116 SkDebugf("pictures size %zd (pictures:%d) ", pictureBytes, pictures);
117 if (regions != 0)
118 SkDebugf("regions size %zd (regions:%d) ", regionBytes, regions);
119 SkDebugf("\n");
120#endif
121}
122
reed@google.comf4cc1872012-07-23 15:04:45 +0000123template <typename T> T* SafeRefReturn(T* obj) {
124 if (obj) {
125 obj->ref();
126 }
127 return obj;
128}
129
reed@android.com8a1c16f2008-12-17 15:59:43 +0000130SkPicturePlayback::SkPicturePlayback(const SkPicturePlayback& src) {
131 this->init();
132
reed@google.comf4cc1872012-07-23 15:04:45 +0000133 fPathHeap = SafeRefReturn(src.fPathHeap);
134 fBitmaps = SafeRefReturn(src.fBitmaps);
135 fMatrices = SafeRefReturn(src.fMatrices);
136 fPaints = SafeRefReturn(src.fPaints);
137 fRegions = SafeRefReturn(src.fRegions);
138 fOpData = SafeRefReturn(src.fOpData);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000139
140 fPictureCount = src.fPictureCount;
141 fPictureRefs = SkNEW_ARRAY(SkPicture*, fPictureCount);
142 for (int i = 0; i < fPictureCount; i++) {
143 fPictureRefs[i] = src.fPictureRefs[i];
144 fPictureRefs[i]->ref();
145 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000146}
147
148void SkPicturePlayback::init() {
149 fBitmaps = NULL;
150 fMatrices = NULL;
151 fPaints = NULL;
152 fPathHeap = NULL;
153 fPictureRefs = NULL;
154 fRegions = NULL;
reed@google.comf4cc1872012-07-23 15:04:45 +0000155 fPictureCount = 0;
reed@google.comddf98a82012-07-21 20:31:09 +0000156 fOpData = NULL;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000157 fFactoryPlayback = NULL;
158}
159
160SkPicturePlayback::~SkPicturePlayback() {
reed@google.comddf98a82012-07-21 20:31:09 +0000161 fOpData->unref();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000162
reed@google.comf4cc1872012-07-23 15:04:45 +0000163 SkSafeUnref(fBitmaps);
164 SkSafeUnref(fMatrices);
165 SkSafeUnref(fPaints);
166 SkSafeUnref(fRegions);
reed@google.com82065d62011-02-07 15:30:46 +0000167 SkSafeUnref(fPathHeap);
168
reed@android.com8a1c16f2008-12-17 15:59:43 +0000169 for (int i = 0; i < fPictureCount; i++) {
170 fPictureRefs[i]->unref();
171 }
172 SkDELETE_ARRAY(fPictureRefs);
reed@google.com82065d62011-02-07 15:30:46 +0000173
reed@android.com8a1c16f2008-12-17 15:59:43 +0000174 SkDELETE(fFactoryPlayback);
175}
176
177void SkPicturePlayback::dumpSize() const {
178 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 +0000179 fOpData->size(),
reed@google.comf4cc1872012-07-23 15:04:45 +0000180 SafeCount(fBitmaps), SafeCount(fBitmaps) * sizeof(SkBitmap),
181 SafeCount(fMatrices), SafeCount(fMatrices) * sizeof(SkMatrix),
182 SafeCount(fPaints), SafeCount(fPaints) * sizeof(SkPaint),
183 SafeCount(fPathHeap),
184 SafeCount(fRegions));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000185}
186
187///////////////////////////////////////////////////////////////////////////////
188///////////////////////////////////////////////////////////////////////////////
189
reed@android.com8a1c16f2008-12-17 15:59:43 +0000190#define PICT_READER_TAG SkSetFourByteTag('r', 'e', 'a', 'd')
191#define PICT_FACTORY_TAG SkSetFourByteTag('f', 'a', 'c', 't')
192#define PICT_TYPEFACE_TAG SkSetFourByteTag('t', 'p', 'f', 'c')
193#define PICT_PICTURE_TAG SkSetFourByteTag('p', 'c', 't', 'r')
reed@google.com67562092012-06-22 15:38:39 +0000194
195// This tag specifies the size of the ReadBuffer, needed for the following tags
196#define PICT_BUFFER_SIZE_TAG SkSetFourByteTag('a', 'r', 'a', 'y')
reed@android.com8a1c16f2008-12-17 15:59:43 +0000197// these are all inside the ARRAYS tag
reed@google.com67562092012-06-22 15:38:39 +0000198#define PICT_BITMAP_BUFFER_TAG SkSetFourByteTag('b', 't', 'm', 'p')
199#define PICT_MATRIX_BUFFER_TAG SkSetFourByteTag('m', 't', 'r', 'x')
200#define PICT_PAINT_BUFFER_TAG SkSetFourByteTag('p', 'n', 't', ' ')
201#define PICT_PATH_BUFFER_TAG SkSetFourByteTag('p', 't', 'h', ' ')
202#define PICT_REGION_BUFFER_TAG SkSetFourByteTag('r', 'g', 'n', ' ')
reed@android.com8a1c16f2008-12-17 15:59:43 +0000203
reed@google.comed384952012-06-22 13:12:17 +0000204// Always write this guy last (with no length field afterwards)
205#define PICT_EOF_TAG SkSetFourByteTag('e', 'o', 'f', ' ')
206
reed@android.com8a1c16f2008-12-17 15:59:43 +0000207#include "SkStream.h"
208
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000209static void writeTagSize(SkOrderedWriteBuffer& buffer, uint32_t tag,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000210 uint32_t size) {
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000211 buffer.writeUInt(tag);
212 buffer.writeUInt(size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000213}
214
215static void writeTagSize(SkWStream* stream, uint32_t tag,
216 uint32_t size) {
217 stream->write32(tag);
218 stream->write32(size);
219}
220
mike@reedtribe.orge9e08cc2011-04-29 01:44:52 +0000221static void writeFactories(SkWStream* stream, const SkFactorySet& rec) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000222 int count = rec.count();
reed@google.com82065d62011-02-07 15:30:46 +0000223
reed@android.com8a1c16f2008-12-17 15:59:43 +0000224 writeTagSize(stream, PICT_FACTORY_TAG, count);
reed@google.com82065d62011-02-07 15:30:46 +0000225
reed@android.com8a1c16f2008-12-17 15:59:43 +0000226 SkAutoSTMalloc<16, SkFlattenable::Factory> storage(count);
227 SkFlattenable::Factory* array = (SkFlattenable::Factory*)storage.get();
mike@reedtribe.orge9e08cc2011-04-29 01:44:52 +0000228 rec.copyToArray(array);
reed@google.com82065d62011-02-07 15:30:46 +0000229
reed@android.com8a1c16f2008-12-17 15:59:43 +0000230 for (int i = 0; i < count; i++) {
231 const char* name = SkFlattenable::FactoryToName(array[i]);
232// SkDebugf("---- write factories [%d] %p <%s>\n", i, array[i], name);
233 if (NULL == name || 0 == *name) {
234 stream->writePackedUInt(0);
235 } else {
236 uint32_t len = strlen(name);
237 stream->writePackedUInt(len);
238 stream->write(name, len);
239 }
240 }
241}
242
mike@reedtribe.orge9e08cc2011-04-29 01:44:52 +0000243static void writeTypefaces(SkWStream* stream, const SkRefCntSet& rec) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000244 int count = rec.count();
reed@google.com82065d62011-02-07 15:30:46 +0000245
reed@android.com8a1c16f2008-12-17 15:59:43 +0000246 writeTagSize(stream, PICT_TYPEFACE_TAG, count);
reed@google.com82065d62011-02-07 15:30:46 +0000247
reed@android.com8a1c16f2008-12-17 15:59:43 +0000248 SkAutoSTMalloc<16, SkTypeface*> storage(count);
249 SkTypeface** array = (SkTypeface**)storage.get();
mike@reedtribe.orge9e08cc2011-04-29 01:44:52 +0000250 rec.copyToArray((SkRefCnt**)array);
reed@google.com82065d62011-02-07 15:30:46 +0000251
reed@android.com8a1c16f2008-12-17 15:59:43 +0000252 for (int i = 0; i < count; i++) {
253 array[i]->serialize(stream);
254 }
255}
256
reed@google.com67562092012-06-22 15:38:39 +0000257void SkPicturePlayback::flattenToBuffer(SkOrderedWriteBuffer& buffer) const {
reed@google.comf4cc1872012-07-23 15:04:45 +0000258 int i, n;
reed@google.com82065d62011-02-07 15:30:46 +0000259
reed@google.comf4cc1872012-07-23 15:04:45 +0000260 if ((n = SafeCount(fBitmaps)) > 0) {
261 writeTagSize(buffer, PICT_BITMAP_BUFFER_TAG, n);
262 for (i = 0; i < n; i++) {
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000263 buffer.writeBitmap((*fBitmaps)[i]);
reed@google.com67562092012-06-22 15:38:39 +0000264 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000265 }
reed@google.com67562092012-06-22 15:38:39 +0000266
reed@google.comf4cc1872012-07-23 15:04:45 +0000267 if ((n = SafeCount(fMatrices)) > 0) {
268 writeTagSize(buffer, PICT_MATRIX_BUFFER_TAG, n);
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000269 for (i = 0; i < n; i++) {
270 buffer.writeMatrix((*fMatrices)[i]);
271 }
272
reed@android.com8a1c16f2008-12-17 15:59:43 +0000273 }
reed@google.com67562092012-06-22 15:38:39 +0000274
reed@google.comf4cc1872012-07-23 15:04:45 +0000275 if ((n = SafeCount(fPaints)) > 0) {
276 writeTagSize(buffer, PICT_PAINT_BUFFER_TAG, n);
277 for (i = 0; i < n; i++) {
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000278 buffer.writePaint((*fPaints)[i]);
reed@google.com67562092012-06-22 15:38:39 +0000279 }
280 }
281
reed@google.comf4cc1872012-07-23 15:04:45 +0000282 if ((n = SafeCount(fPathHeap)) > 0) {
283 writeTagSize(buffer, PICT_PATH_BUFFER_TAG, n);
284 fPathHeap->flatten(buffer);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000285 }
reed@google.com67562092012-06-22 15:38:39 +0000286
reed@google.comf4cc1872012-07-23 15:04:45 +0000287 if ((n = SafeCount(fRegions)) > 0) {
288 writeTagSize(buffer, PICT_REGION_BUFFER_TAG, n);
289 for (i = 0; i < n; i++) {
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000290 buffer.writeRegion((*fRegions)[i]);
reed@google.com67562092012-06-22 15:38:39 +0000291 }
292 }
293}
reed@google.com82065d62011-02-07 15:30:46 +0000294
reed@google.com67562092012-06-22 15:38:39 +0000295void SkPicturePlayback::serialize(SkWStream* stream) const {
reed@google.comddf98a82012-07-21 20:31:09 +0000296 writeTagSize(stream, PICT_READER_TAG, fOpData->size());
297 stream->write(fOpData->bytes(), fOpData->size());
reed@google.com67562092012-06-22 15:38:39 +0000298
299 if (fPictureCount > 0) {
300 writeTagSize(stream, PICT_PICTURE_TAG, fPictureCount);
301 for (int i = 0; i < fPictureCount; i++) {
302 fPictureRefs[i]->serialize(stream);
303 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000304 }
reed@google.com82065d62011-02-07 15:30:46 +0000305
reed@google.com67562092012-06-22 15:38:39 +0000306 // Write some of our data into a writebuffer, and then serialize that
307 // into our stream
308 {
309 SkRefCntSet typefaceSet;
310 SkFactorySet factSet;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000311
reed@google.com67562092012-06-22 15:38:39 +0000312 SkOrderedWriteBuffer buffer(1024);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000313
reed@google.com67562092012-06-22 15:38:39 +0000314 buffer.setFlags(SkFlattenableWriteBuffer::kCrossProcess_Flag);
315 buffer.setTypefaceRecorder(&typefaceSet);
316 buffer.setFactoryRecorder(&factSet);
reed@google.com34342f62012-06-25 14:36:28 +0000317
reed@google.com67562092012-06-22 15:38:39 +0000318 this->flattenToBuffer(buffer);
319
320 // We have to write these to sets into the stream *before* we write
321 // the buffer, since parsing that buffer will require that we already
322 // have these sets available to use.
323 writeFactories(stream, factSet);
324 writeTypefaces(stream, typefaceSet);
325
326 writeTagSize(stream, PICT_BUFFER_SIZE_TAG, buffer.size());
327 buffer.writeToStream(stream);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000328 }
reed@google.com82065d62011-02-07 15:30:46 +0000329
reed@google.comed384952012-06-22 13:12:17 +0000330 stream->write32(PICT_EOF_TAG);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000331}
332
333///////////////////////////////////////////////////////////////////////////////
334
reed@google.com34342f62012-06-25 14:36:28 +0000335/**
336 * Return the corresponding SkFlattenableReadBuffer flags, given a set of
337 * SkPictInfo flags.
338 */
339static uint32_t pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags) {
340 static const struct {
341 uint32_t fSrc;
342 uint32_t fDst;
343 } gSD[] = {
344 { SkPictInfo::kCrossProcess_Flag, SkFlattenableReadBuffer::kCrossProcess_Flag },
345 { SkPictInfo::kScalarIsFloat_Flag, SkFlattenableReadBuffer::kScalarIsFloat_Flag },
346 { SkPictInfo::kPtrIs64Bit_Flag, SkFlattenableReadBuffer::kPtrIs64Bit_Flag },
347 };
348
349 uint32_t rbMask = 0;
350 for (size_t i = 0; i < SK_ARRAY_COUNT(gSD); ++i) {
351 if (pictInfoFlags & gSD[i].fSrc) {
352 rbMask |= gSD[i].fDst;
353 }
354 }
355 return rbMask;
356}
357
reed@google.com67562092012-06-22 15:38:39 +0000358bool SkPicturePlayback::parseStreamTag(SkStream* stream, const SkPictInfo& info,
359 uint32_t tag, size_t size) {
360 /*
361 * By the time we encounter BUFFER_SIZE_TAG, we need to have already seen
362 * its dependents: FACTORY_TAG and TYPEFACE_TAG. These two are not required
363 * but if they are present, they need to have been seen before the buffer.
364 *
365 * We assert that if/when we see either of these, that we have not yet seen
366 * the buffer tag, because if we have, then its too-late to deal with the
367 * factories or typefaces.
368 */
369 bool haveBuffer = false;
370
371 switch (tag) {
372 case PICT_READER_TAG: {
373 void* storage = sk_malloc_throw(size);
374 stream->read(storage, size);
reed@google.comddf98a82012-07-21 20:31:09 +0000375 SkASSERT(NULL == fOpData);
376 fOpData = SkData::NewFromMalloc(storage, size);
reed@google.com67562092012-06-22 15:38:39 +0000377 } break;
378 case PICT_FACTORY_TAG: {
379 SkASSERT(!haveBuffer);
380 fFactoryPlayback = SkNEW_ARGS(SkFactoryPlayback, (size));
381 for (size_t i = 0; i < size; i++) {
382 SkString str;
383 int len = stream->readPackedUInt();
384 str.resize(len);
385 stream->read(str.writable_str(), len);
386 fFactoryPlayback->base()[i] = SkFlattenable::NameToFactory(str.c_str());
387 }
388 } break;
389 case PICT_TYPEFACE_TAG: {
390 SkASSERT(!haveBuffer);
391 fTFPlayback.setCount(size);
392 for (size_t i = 0; i < size; i++) {
393 SkSafeUnref(fTFPlayback.set(i, SkTypeface::Deserialize(stream)));
394 }
395 } break;
396 case PICT_PICTURE_TAG: {
397 fPictureCount = size;
398 fPictureRefs = SkNEW_ARRAY(SkPicture*, fPictureCount);
399 for (int i = 0; i < fPictureCount; i++) {
400 fPictureRefs[i] = SkNEW_ARGS(SkPicture, (stream));
401 }
402 } break;
403 case PICT_BUFFER_SIZE_TAG: {
404 SkAutoMalloc storage(size);
405 stream->read(storage.get(), size);
406
407 SkOrderedReadBuffer buffer(storage.get(), size);
reed@google.com34342f62012-06-25 14:36:28 +0000408 buffer.setFlags(pictInfoFlagsToReadBufferFlags(info.fFlags));
409
reed@google.com67562092012-06-22 15:38:39 +0000410 fFactoryPlayback->setupBuffer(buffer);
411 fTFPlayback.setupBuffer(buffer);
412
413 while (!buffer.eof()) {
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000414 tag = buffer.readUInt();
415 size = buffer.readUInt();
reed@google.com67562092012-06-22 15:38:39 +0000416 if (!this->parseBufferTag(buffer, tag, size)) {
417 return false;
418 }
419 }
420 haveBuffer = true;
421 } break;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000422 }
reed@google.com67562092012-06-22 15:38:39 +0000423 return true; // success
reed@android.com8a1c16f2008-12-17 15:59:43 +0000424}
425
reed@google.com67562092012-06-22 15:38:39 +0000426bool SkPicturePlayback::parseBufferTag(SkOrderedReadBuffer& buffer,
427 uint32_t tag, size_t size) {
428 switch (tag) {
429 case PICT_BITMAP_BUFFER_TAG: {
reed@google.comf4cc1872012-07-23 15:04:45 +0000430 fBitmaps = SkTRefArray<SkBitmap>::Create(size);
431 for (size_t i = 0; i < size; ++i) {
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000432 buffer.readBitmap(&fBitmaps->writableAt(i));
reed@google.com67562092012-06-22 15:38:39 +0000433 }
434 } break;
435 case PICT_MATRIX_BUFFER_TAG:
reed@google.comf4cc1872012-07-23 15:04:45 +0000436 fMatrices = SkTRefArray<SkMatrix>::Create(size);
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000437 for (size_t i = 0; i < size; ++i) {
438 buffer.readMatrix(&fMatrices->writableAt(i));
439 }
reed@google.com67562092012-06-22 15:38:39 +0000440 break;
441 case PICT_PAINT_BUFFER_TAG: {
reed@google.comf4cc1872012-07-23 15:04:45 +0000442 fPaints = SkTRefArray<SkPaint>::Create(size);
443 for (size_t i = 0; i < size; ++i) {
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000444 buffer.readPaint(&fPaints->writableAt(i));
reed@google.com67562092012-06-22 15:38:39 +0000445 }
446 } break;
447 case PICT_PATH_BUFFER_TAG:
448 if (size > 0) {
449 fPathHeap = SkNEW_ARGS(SkPathHeap, (buffer));
450 }
451 break;
452 case PICT_REGION_BUFFER_TAG: {
reed@google.comf4cc1872012-07-23 15:04:45 +0000453 fRegions = SkTRefArray<SkRegion>::Create(size);
454 for (size_t i = 0; i < size; ++i) {
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000455 buffer.readRegion(&fRegions->writableAt(i));
reed@google.com67562092012-06-22 15:38:39 +0000456 }
457 } break;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000458 }
reed@google.com67562092012-06-22 15:38:39 +0000459 return true; // success
reed@android.com8a1c16f2008-12-17 15:59:43 +0000460}
461
reed@google.com67562092012-06-22 15:38:39 +0000462SkPicturePlayback::SkPicturePlayback(SkStream* stream, const SkPictInfo& info,
463 bool* isValid) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000464 this->init();
465
reed@google.com67562092012-06-22 15:38:39 +0000466 *isValid = false; // wait until we're done parsing to mark as true
467 for (;;) {
468 uint32_t tag = stream->readU32();
469 if (PICT_EOF_TAG == tag) {
470 break;
471 }
reed@google.com82065d62011-02-07 15:30:46 +0000472
reed@google.comed384952012-06-22 13:12:17 +0000473 uint32_t size = stream->readU32();
reed@google.com67562092012-06-22 15:38:39 +0000474 if (!this->parseStreamTag(stream, info, tag, size)) {
475 return; // we're invalid
reed@android.com8a1c16f2008-12-17 15:59:43 +0000476 }
477 }
reed@google.com67562092012-06-22 15:38:39 +0000478 *isValid = true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000479}
480
481///////////////////////////////////////////////////////////////////////////////
482///////////////////////////////////////////////////////////////////////////////
483
reed@android.comae814c82009-02-13 14:56:09 +0000484#ifdef SPEW_CLIP_SKIPPING
485struct SkipClipRec {
486 int fCount;
487 size_t fSize;
reed@google.com82065d62011-02-07 15:30:46 +0000488
reed@android.comae814c82009-02-13 14:56:09 +0000489 SkipClipRec() {
490 fCount = 0;
491 fSize = 0;
492 }
reed@google.com82065d62011-02-07 15:30:46 +0000493
reed@android.comae814c82009-02-13 14:56:09 +0000494 void recordSkip(size_t bytes) {
495 fCount += 1;
496 fSize += bytes;
497 }
498};
499#endif
500
reed@android.com8a1c16f2008-12-17 15:59:43 +0000501void SkPicturePlayback::draw(SkCanvas& canvas) {
502#ifdef ENABLE_TIME_DRAW
503 SkAutoTime at("SkPicture::draw", 50);
504#endif
reed@google.com82065d62011-02-07 15:30:46 +0000505
reed@android.comae814c82009-02-13 14:56:09 +0000506#ifdef SPEW_CLIP_SKIPPING
507 SkipClipRec skipRect, skipRegion, skipPath;
508#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000509
djsollen@google.com56c69772011-11-08 19:00:26 +0000510#ifdef SK_BUILD_FOR_ANDROID
djsollen@google.comf5dbe2f2011-04-15 13:41:26 +0000511 SkAutoMutexAcquire autoMutex(fDrawMutex);
512#endif
513
reed@google.comddf98a82012-07-21 20:31:09 +0000514 SkReader32 reader(fOpData->bytes(), fOpData->size());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000515 TextContainer text;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000516
reed@google.comddf98a82012-07-21 20:31:09 +0000517 while (!reader.eof()) {
518 switch (reader.readInt()) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000519 case CLIP_PATH: {
reed@google.comddf98a82012-07-21 20:31:09 +0000520 const SkPath& path = getPath(reader);
521 uint32_t packed = reader.readInt();
reed@google.com83ab4952011-11-11 21:34:54 +0000522 SkRegion::Op op = ClipParams_unpackRegionOp(packed);
523 bool doAA = ClipParams_unpackDoAA(packed);
reed@google.comddf98a82012-07-21 20:31:09 +0000524 size_t offsetToRestore = reader.readInt();
junov@chromium.org9fa4d0c2012-07-09 20:53:37 +0000525 SkASSERT(!offsetToRestore || \
reed@google.comddf98a82012-07-21 20:31:09 +0000526 offsetToRestore >= reader.offset());
reed@google.com83ab4952011-11-11 21:34:54 +0000527 if (!canvas.clipPath(path, op, doAA) && offsetToRestore) {
reed@android.comae814c82009-02-13 14:56:09 +0000528#ifdef SPEW_CLIP_SKIPPING
reed@google.comddf98a82012-07-21 20:31:09 +0000529 skipPath.recordSkip(offsetToRestore - reader.offset());
reed@android.comae814c82009-02-13 14:56:09 +0000530#endif
reed@google.comddf98a82012-07-21 20:31:09 +0000531 reader.setOffset(offsetToRestore);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000532 }
533 } break;
534 case CLIP_REGION: {
reed@google.comddf98a82012-07-21 20:31:09 +0000535 const SkRegion& region = getRegion(reader);
536 uint32_t packed = reader.readInt();
reed@google.com83ab4952011-11-11 21:34:54 +0000537 SkRegion::Op op = ClipParams_unpackRegionOp(packed);
reed@google.comddf98a82012-07-21 20:31:09 +0000538 size_t offsetToRestore = reader.readInt();
junov@chromium.org9fa4d0c2012-07-09 20:53:37 +0000539 SkASSERT(!offsetToRestore || \
reed@google.comddf98a82012-07-21 20:31:09 +0000540 offsetToRestore >= reader.offset());
reed@google.com45482d12011-08-29 19:02:39 +0000541 if (!canvas.clipRegion(region, op) && offsetToRestore) {
reed@android.comae814c82009-02-13 14:56:09 +0000542#ifdef SPEW_CLIP_SKIPPING
reed@google.comddf98a82012-07-21 20:31:09 +0000543 skipRegion.recordSkip(offsetToRestore - reader.offset());
reed@android.comae814c82009-02-13 14:56:09 +0000544#endif
reed@google.comddf98a82012-07-21 20:31:09 +0000545 reader.setOffset(offsetToRestore);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000546 }
547 } break;
548 case CLIP_RECT: {
reed@google.comddf98a82012-07-21 20:31:09 +0000549 const SkRect& rect = reader.skipT<SkRect>();
550 uint32_t packed = reader.readInt();
reed@google.com83ab4952011-11-11 21:34:54 +0000551 SkRegion::Op op = ClipParams_unpackRegionOp(packed);
552 bool doAA = ClipParams_unpackDoAA(packed);
reed@google.comddf98a82012-07-21 20:31:09 +0000553 size_t offsetToRestore = reader.readInt();
junov@chromium.org9fa4d0c2012-07-09 20:53:37 +0000554 SkASSERT(!offsetToRestore || \
reed@google.comddf98a82012-07-21 20:31:09 +0000555 offsetToRestore >= reader.offset());
reed@google.com83ab4952011-11-11 21:34:54 +0000556 if (!canvas.clipRect(rect, op, doAA) && offsetToRestore) {
reed@android.comae814c82009-02-13 14:56:09 +0000557#ifdef SPEW_CLIP_SKIPPING
reed@google.comddf98a82012-07-21 20:31:09 +0000558 skipRect.recordSkip(offsetToRestore - reader.offset());
reed@android.comae814c82009-02-13 14:56:09 +0000559#endif
reed@google.comddf98a82012-07-21 20:31:09 +0000560 reader.setOffset(offsetToRestore);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000561 }
562 } break;
563 case CONCAT:
reed@google.comddf98a82012-07-21 20:31:09 +0000564 canvas.concat(*getMatrix(reader));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000565 break;
566 case DRAW_BITMAP: {
reed@google.comddf98a82012-07-21 20:31:09 +0000567 const SkPaint* paint = getPaint(reader);
568 const SkBitmap& bitmap = getBitmap(reader);
569 const SkPoint& loc = reader.skipT<SkPoint>();
reed@google.coma5adf532011-09-07 13:52:17 +0000570 canvas.drawBitmap(bitmap, loc.fX, loc.fY, paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000571 } break;
572 case DRAW_BITMAP_RECT: {
reed@google.comddf98a82012-07-21 20:31:09 +0000573 const SkPaint* paint = getPaint(reader);
574 const SkBitmap& bitmap = getBitmap(reader);
575 const SkIRect* src = this->getIRectPtr(reader); // may be null
576 const SkRect& dst = reader.skipT<SkRect>(); // required
reed@google.coma5adf532011-09-07 13:52:17 +0000577 canvas.drawBitmapRect(bitmap, src, dst, paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000578 } break;
579 case DRAW_BITMAP_MATRIX: {
reed@google.comddf98a82012-07-21 20:31:09 +0000580 const SkPaint* paint = getPaint(reader);
581 const SkBitmap& bitmap = getBitmap(reader);
582 const SkMatrix* matrix = getMatrix(reader);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000583 canvas.drawBitmapMatrix(bitmap, *matrix, paint);
584 } break;
reed@google.comf0b5e112011-09-07 11:57:34 +0000585 case DRAW_BITMAP_NINE: {
reed@google.comddf98a82012-07-21 20:31:09 +0000586 const SkPaint* paint = getPaint(reader);
587 const SkBitmap& bitmap = getBitmap(reader);
588 const SkIRect& src = reader.skipT<SkIRect>();
589 const SkRect& dst = reader.skipT<SkRect>();
reed@google.coma5adf532011-09-07 13:52:17 +0000590 canvas.drawBitmapNine(bitmap, src, dst, paint);
reed@google.comf0b5e112011-09-07 11:57:34 +0000591 } break;
reed@google.com2a981812011-04-14 18:59:28 +0000592 case DRAW_CLEAR:
reed@google.comddf98a82012-07-21 20:31:09 +0000593 canvas.clear(reader.readInt());
reed@google.com2a981812011-04-14 18:59:28 +0000594 break;
reed@android.comcb608442009-12-04 21:32:27 +0000595 case DRAW_DATA: {
reed@google.comddf98a82012-07-21 20:31:09 +0000596 size_t length = reader.readInt();
597 canvas.drawData(reader.skip(length), length);
reed@android.comcb608442009-12-04 21:32:27 +0000598 // skip handles padding the read out to a multiple of 4
599 } break;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000600 case DRAW_PAINT:
reed@google.comddf98a82012-07-21 20:31:09 +0000601 canvas.drawPaint(*getPaint(reader));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000602 break;
603 case DRAW_PATH: {
reed@google.comddf98a82012-07-21 20:31:09 +0000604 const SkPaint& paint = *getPaint(reader);
605 canvas.drawPath(getPath(reader), paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000606 } break;
607 case DRAW_PICTURE:
reed@google.comddf98a82012-07-21 20:31:09 +0000608 canvas.drawPicture(getPicture(reader));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000609 break;
610 case DRAW_POINTS: {
reed@google.comddf98a82012-07-21 20:31:09 +0000611 const SkPaint& paint = *getPaint(reader);
612 SkCanvas::PointMode mode = (SkCanvas::PointMode)reader.readInt();
613 size_t count = reader.readInt();
614 const SkPoint* pts = (const SkPoint*)reader.skip(sizeof(SkPoint) * count);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000615 canvas.drawPoints(mode, count, pts, paint);
616 } break;
617 case DRAW_POS_TEXT: {
reed@google.comddf98a82012-07-21 20:31:09 +0000618 const SkPaint& paint = *getPaint(reader);
619 getText(reader, &text);
620 size_t points = reader.readInt();
621 const SkPoint* pos = (const SkPoint*)reader.skip(points * sizeof(SkPoint));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000622 canvas.drawPosText(text.text(), text.length(), pos, paint);
623 } break;
reed@google.com9efd9a02012-01-30 15:41:43 +0000624 case DRAW_POS_TEXT_TOP_BOTTOM: {
reed@google.comddf98a82012-07-21 20:31:09 +0000625 const SkPaint& paint = *getPaint(reader);
626 getText(reader, &text);
627 size_t points = reader.readInt();
628 const SkPoint* pos = (const SkPoint*)reader.skip(points * sizeof(SkPoint));
629 const SkScalar top = reader.readScalar();
630 const SkScalar bottom = reader.readScalar();
reed@google.com9efd9a02012-01-30 15:41:43 +0000631 if (!canvas.quickRejectY(top, bottom, SkCanvas::kAA_EdgeType)) {
632 canvas.drawPosText(text.text(), text.length(), pos, paint);
633 }
634 } break;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000635 case DRAW_POS_TEXT_H: {
reed@google.comddf98a82012-07-21 20:31:09 +0000636 const SkPaint& paint = *getPaint(reader);
637 getText(reader, &text);
638 size_t xCount = reader.readInt();
639 const SkScalar constY = reader.readScalar();
640 const SkScalar* xpos = (const SkScalar*)reader.skip(xCount * sizeof(SkScalar));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000641 canvas.drawPosTextH(text.text(), text.length(), xpos, constY,
642 paint);
643 } break;
644 case DRAW_POS_TEXT_H_TOP_BOTTOM: {
reed@google.comddf98a82012-07-21 20:31:09 +0000645 const SkPaint& paint = *getPaint(reader);
646 getText(reader, &text);
647 size_t xCount = reader.readInt();
648 const SkScalar* xpos = (const SkScalar*)reader.skip((3 + xCount) * sizeof(SkScalar));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000649 const SkScalar top = *xpos++;
650 const SkScalar bottom = *xpos++;
651 const SkScalar constY = *xpos++;
652 if (!canvas.quickRejectY(top, bottom, SkCanvas::kAA_EdgeType)) {
653 canvas.drawPosTextH(text.text(), text.length(), xpos,
654 constY, paint);
655 }
656 } break;
657 case DRAW_RECT: {
reed@google.comddf98a82012-07-21 20:31:09 +0000658 const SkPaint& paint = *getPaint(reader);
659 canvas.drawRect(reader.skipT<SkRect>(), paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000660 } break;
661 case DRAW_SPRITE: {
reed@google.comddf98a82012-07-21 20:31:09 +0000662 const SkPaint* paint = getPaint(reader);
663 const SkBitmap& bitmap = getBitmap(reader);
664 int left = reader.readInt();
665 int top = reader.readInt();
reed@google.com82065d62011-02-07 15:30:46 +0000666 canvas.drawSprite(bitmap, left, top, paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000667 } break;
668 case DRAW_TEXT: {
reed@google.comddf98a82012-07-21 20:31:09 +0000669 const SkPaint& paint = *getPaint(reader);
670 getText(reader, &text);
671 SkScalar x = reader.readScalar();
672 SkScalar y = reader.readScalar();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000673 canvas.drawText(text.text(), text.length(), x, y, paint);
674 } break;
675 case DRAW_TEXT_TOP_BOTTOM: {
reed@google.comddf98a82012-07-21 20:31:09 +0000676 const SkPaint& paint = *getPaint(reader);
677 getText(reader, &text);
678 const SkScalar* ptr = (const SkScalar*)reader.skip(4 * sizeof(SkScalar));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000679 // ptr[0] == x
680 // ptr[1] == y
681 // ptr[2] == top
682 // ptr[3] == bottom
683 if (!canvas.quickRejectY(ptr[2], ptr[3],
684 SkCanvas::kAA_EdgeType)) {
685 canvas.drawText(text.text(), text.length(), ptr[0], ptr[1],
686 paint);
687 }
688 } break;
689 case DRAW_TEXT_ON_PATH: {
reed@google.comddf98a82012-07-21 20:31:09 +0000690 const SkPaint& paint = *getPaint(reader);
691 getText(reader, &text);
692 const SkPath& path = getPath(reader);
693 const SkMatrix* matrix = getMatrix(reader);
reed@google.com82065d62011-02-07 15:30:46 +0000694 canvas.drawTextOnPath(text.text(), text.length(), path,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000695 matrix, paint);
696 } break;
697 case DRAW_VERTICES: {
reed@google.comddf98a82012-07-21 20:31:09 +0000698 const SkPaint& paint = *getPaint(reader);
699 DrawVertexFlags flags = (DrawVertexFlags)reader.readInt();
700 SkCanvas::VertexMode vmode = (SkCanvas::VertexMode)reader.readInt();
701 int vCount = reader.readInt();
702 const SkPoint* verts = (const SkPoint*)reader.skip(
reed@android.com8a1c16f2008-12-17 15:59:43 +0000703 vCount * sizeof(SkPoint));
704 const SkPoint* texs = NULL;
705 const SkColor* colors = NULL;
706 const uint16_t* indices = NULL;
707 int iCount = 0;
708 if (flags & DRAW_VERTICES_HAS_TEXS) {
reed@google.comddf98a82012-07-21 20:31:09 +0000709 texs = (const SkPoint*)reader.skip(
reed@android.com8a1c16f2008-12-17 15:59:43 +0000710 vCount * sizeof(SkPoint));
711 }
712 if (flags & DRAW_VERTICES_HAS_COLORS) {
reed@google.comddf98a82012-07-21 20:31:09 +0000713 colors = (const SkColor*)reader.skip(
reed@android.com8a1c16f2008-12-17 15:59:43 +0000714 vCount * sizeof(SkColor));
715 }
716 if (flags & DRAW_VERTICES_HAS_INDICES) {
reed@google.comddf98a82012-07-21 20:31:09 +0000717 iCount = reader.readInt();
718 indices = (const uint16_t*)reader.skip(
reed@android.com8a1c16f2008-12-17 15:59:43 +0000719 iCount * sizeof(uint16_t));
720 }
721 canvas.drawVertices(vmode, vCount, verts, texs, colors, NULL,
722 indices, iCount, paint);
723 } break;
724 case RESTORE:
725 canvas.restore();
726 break;
727 case ROTATE:
reed@google.comddf98a82012-07-21 20:31:09 +0000728 canvas.rotate(reader.readScalar());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000729 break;
730 case SAVE:
reed@google.comddf98a82012-07-21 20:31:09 +0000731 canvas.save((SkCanvas::SaveFlags) reader.readInt());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000732 break;
733 case SAVE_LAYER: {
reed@google.comddf98a82012-07-21 20:31:09 +0000734 const SkRect* boundsPtr = getRectPtr(reader);
735 const SkPaint* paint = getPaint(reader);
736 canvas.saveLayer(boundsPtr, paint, (SkCanvas::SaveFlags) reader.readInt());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000737 } break;
738 case SCALE: {
reed@google.comddf98a82012-07-21 20:31:09 +0000739 SkScalar sx = reader.readScalar();
740 SkScalar sy = reader.readScalar();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000741 canvas.scale(sx, sy);
742 } break;
reed@android.com6e073b92009-01-06 15:03:30 +0000743 case SET_MATRIX:
reed@google.comddf98a82012-07-21 20:31:09 +0000744 canvas.setMatrix(*getMatrix(reader));
reed@android.com6e073b92009-01-06 15:03:30 +0000745 break;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000746 case SKEW: {
reed@google.comddf98a82012-07-21 20:31:09 +0000747 SkScalar sx = reader.readScalar();
748 SkScalar sy = reader.readScalar();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000749 canvas.skew(sx, sy);
750 } break;
751 case TRANSLATE: {
reed@google.comddf98a82012-07-21 20:31:09 +0000752 SkScalar dx = reader.readScalar();
753 SkScalar dy = reader.readScalar();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000754 canvas.translate(dx, dy);
755 } break;
756 default:
757 SkASSERT(0);
758 }
759 }
reed@google.com82065d62011-02-07 15:30:46 +0000760
reed@android.comae814c82009-02-13 14:56:09 +0000761#ifdef SPEW_CLIP_SKIPPING
762 {
763 size_t size = skipRect.fSize + skipPath.fSize + skipRegion.fSize;
764 SkDebugf("--- Clip skips %d%% rect:%d path:%d rgn:%d\n",
reed@google.comddf98a82012-07-21 20:31:09 +0000765 size * 100 / reader.offset(), skipRect.fCount, skipPath.fCount,
reed@android.comae814c82009-02-13 14:56:09 +0000766 skipRegion.fCount);
767 }
768#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000769// this->dumpSize();
770}
771
772void SkPicturePlayback::abort() {
reed@google.comddf98a82012-07-21 20:31:09 +0000773 SkASSERT(!"not supported");
774// fReader.skip(fReader.size() - fReader.offset());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000775}
776
777///////////////////////////////////////////////////////////////////////////////
778
reed@android.com8a1c16f2008-12-17 15:59:43 +0000779#ifdef SK_DEBUG_SIZE
reed@google.com82065d62011-02-07 15:30:46 +0000780int SkPicturePlayback::size(size_t* sizePtr) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000781 int objects = bitmaps(sizePtr);
782 objects += paints(sizePtr);
783 objects += paths(sizePtr);
784 objects += pictures(sizePtr);
785 objects += regions(sizePtr);
reed@google.comddf98a82012-07-21 20:31:09 +0000786 *sizePtr = fOpData.size();
reed@google.com82065d62011-02-07 15:30:46 +0000787 return objects;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000788}
789
790int SkPicturePlayback::bitmaps(size_t* size) {
791 size_t result = 0;
792 for (int index = 0; index < fBitmapCount; index++) {
793 // const SkBitmap& bitmap = fBitmaps[index];
794 result += sizeof(SkBitmap); // bitmap->size();
795 }
796 *size = result;
797 return fBitmapCount;
798}
799
800int SkPicturePlayback::paints(size_t* size) {
801 size_t result = 0;
802 for (int index = 0; index < fPaintCount; index++) {
803 // const SkPaint& paint = fPaints[index];
804 result += sizeof(SkPaint); // paint->size();
805 }
806 *size = result;
807 return fPaintCount;
808}
809
810int SkPicturePlayback::paths(size_t* size) {
811 size_t result = 0;
812 for (int index = 0; index < fPathCount; index++) {
813 const SkPath& path = fPaths[index];
814 result += path.flatten(NULL);
815 }
816 *size = result;
817 return fPathCount;
818}
819
820int SkPicturePlayback::regions(size_t* size) {
821 size_t result = 0;
822 for (int index = 0; index < fRegionCount; index++) {
823 // const SkRegion& region = fRegions[index];
824 result += sizeof(SkRegion); // region->size();
825 }
826 *size = result;
827 return fRegionCount;
828}
829#endif
830
831#ifdef SK_DEBUG_DUMP
832void SkPicturePlayback::dumpBitmap(const SkBitmap& bitmap) const {
833 char pBuffer[DUMP_BUFFER_SIZE];
834 char* bufferPtr = pBuffer;
835 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
836 "BitmapData bitmap%p = {", &bitmap);
837 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
838 "{kWidth, %d}, ", bitmap.width());
839 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
840 "{kHeight, %d}, ", bitmap.height());
841 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
842 "{kRowBytes, %d}, ", bitmap.rowBytes());
843// start here;
844 SkDebugf("%s{0}};\n", pBuffer);
845}
846
847void dumpMatrix(const SkMatrix& matrix) const {
848 SkMatrix defaultMatrix;
849 defaultMatrix.reset();
850 char pBuffer[DUMP_BUFFER_SIZE];
851 char* bufferPtr = pBuffer;
852 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
853 "MatrixData matrix%p = {", &matrix);
854 SkScalar scaleX = matrix.getScaleX();
855 if (scaleX != defaultMatrix.getScaleX())
856 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
857 "{kScaleX, %g}, ", SkScalarToFloat(scaleX));
858 SkScalar scaleY = matrix.getScaleY();
859 if (scaleY != defaultMatrix.getScaleY())
860 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
861 "{kScaleY, %g}, ", SkScalarToFloat(scaleY));
862 SkScalar skewX = matrix.getSkewX();
863 if (skewX != defaultMatrix.getSkewX())
864 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
865 "{kSkewX, %g}, ", SkScalarToFloat(skewX));
866 SkScalar skewY = matrix.getSkewY();
867 if (skewY != defaultMatrix.getSkewY())
868 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
869 "{kSkewY, %g}, ", SkScalarToFloat(skewY));
870 SkScalar translateX = matrix.getTranslateX();
871 if (translateX != defaultMatrix.getTranslateX())
872 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
873 "{kTranslateX, %g}, ", SkScalarToFloat(translateX));
874 SkScalar translateY = matrix.getTranslateY();
875 if (translateY != defaultMatrix.getTranslateY())
876 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
877 "{kTranslateY, %g}, ", SkScalarToFloat(translateY));
878 SkScalar perspX = matrix.getPerspX();
879 if (perspX != defaultMatrix.getPerspX())
880 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
881 "{kPerspX, %g}, ", SkFractToFloat(perspX));
882 SkScalar perspY = matrix.getPerspY();
883 if (perspY != defaultMatrix.getPerspY())
884 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
885 "{kPerspY, %g}, ", SkFractToFloat(perspY));
886 SkDebugf("%s{0}};\n", pBuffer);
887}
888
889void dumpPaint(const SkPaint& paint) const {
890 SkPaint defaultPaint;
891 char pBuffer[DUMP_BUFFER_SIZE];
892 char* bufferPtr = pBuffer;
893 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
894 "PaintPointers paintPtrs%p = {", &paint);
895 const SkTypeface* typeface = paint.getTypeface();
896 if (typeface != defaultPaint.getTypeface())
897 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
898 "{kTypeface, %p}, ", typeface);
899 const SkPathEffect* pathEffect = paint.getPathEffect();
900 if (pathEffect != defaultPaint.getPathEffect())
901 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
902 "{kPathEffect, %p}, ", pathEffect);
903 const SkShader* shader = paint.getShader();
904 if (shader != defaultPaint.getShader())
905 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
906 "{kShader, %p}, ", shader);
907 const SkXfermode* xfermode = paint.getXfermode();
908 if (xfermode != defaultPaint.getXfermode())
909 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
910 "{kXfermode, %p}, ", xfermode);
911 const SkMaskFilter* maskFilter = paint.getMaskFilter();
912 if (maskFilter != defaultPaint.getMaskFilter())
913 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
914 "{kMaskFilter, %p}, ", maskFilter);
915 const SkColorFilter* colorFilter = paint.getColorFilter();
916 if (colorFilter != defaultPaint.getColorFilter())
917 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
918 "{kColorFilter, %p}, ", colorFilter);
919 const SkRasterizer* rasterizer = paint.getRasterizer();
920 if (rasterizer != defaultPaint.getRasterizer())
921 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
922 "{kRasterizer, %p}, ", rasterizer);
923 const SkDrawLooper* drawLooper = paint.getLooper();
924 if (drawLooper != defaultPaint.getLooper())
925 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
926 "{kDrawLooper, %p}, ", drawLooper);
927 SkDebugf("%s{0}};\n", pBuffer);
928 bufferPtr = pBuffer;
929 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
930 "PaintScalars paintScalars%p = {", &paint);
931 SkScalar textSize = paint.getTextSize();
932 if (textSize != defaultPaint.getTextSize())
933 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
934 "{kTextSize, %g}, ", SkScalarToFloat(textSize));
935 SkScalar textScaleX = paint.getTextScaleX();
936 if (textScaleX != defaultPaint.getTextScaleX())
937 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
938 "{kTextScaleX, %g}, ", SkScalarToFloat(textScaleX));
939 SkScalar textSkewX = paint.getTextSkewX();
940 if (textSkewX != defaultPaint.getTextSkewX())
941 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
942 "{kTextSkewX, %g}, ", SkScalarToFloat(textSkewX));
943 SkScalar strokeWidth = paint.getStrokeWidth();
944 if (strokeWidth != defaultPaint.getStrokeWidth())
945 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
946 "{kStrokeWidth, %g}, ", SkScalarToFloat(strokeWidth));
947 SkScalar strokeMiter = paint.getStrokeMiter();
948 if (strokeMiter != defaultPaint.getStrokeMiter())
949 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
950 "{kStrokeMiter, %g}, ", SkScalarToFloat(strokeMiter));
951 SkDebugf("%s{0}};\n", pBuffer);
952 bufferPtr = pBuffer;
953 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
954 "PaintInts = paintInts%p = {", &paint);
955 unsigned color = paint.getColor();
956 if (color != defaultPaint.getColor())
957 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
958 "{kColor, 0x%x}, ", color);
959 unsigned flags = paint.getFlags();
960 if (flags != defaultPaint.getFlags())
961 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
962 "{kFlags, 0x%x}, ", flags);
963 int align = paint.getTextAlign();
964 if (align != defaultPaint.getTextAlign())
965 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
966 "{kAlign, 0x%x}, ", align);
967 int strokeCap = paint.getStrokeCap();
968 if (strokeCap != defaultPaint.getStrokeCap())
969 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
970 "{kStrokeCap, 0x%x}, ", strokeCap);
971 int strokeJoin = paint.getStrokeJoin();
972 if (strokeJoin != defaultPaint.getStrokeJoin())
973 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
974 "{kAlign, 0x%x}, ", strokeJoin);
975 int style = paint.getStyle();
976 if (style != defaultPaint.getStyle())
977 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
978 "{kStyle, 0x%x}, ", style);
979 int textEncoding = paint.getTextEncoding();
980 if (textEncoding != defaultPaint.getTextEncoding())
981 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
982 "{kTextEncoding, 0x%x}, ", textEncoding);
983 SkDebugf("%s{0}};\n", pBuffer);
984
985 SkDebugf("PaintData paint%p = {paintPtrs%p, paintScalars%p, paintInts%p};\n",
986 &paint, &paint, &paint, &paint);
987}
988
989void SkPicturePlayback::dumpPath(const SkPath& path) const {
990 SkDebugf("path dump unimplemented\n");
991}
992
993void SkPicturePlayback::dumpPicture(const SkPicture& picture) const {
994 SkDebugf("picture dump unimplemented\n");
995}
996
997void SkPicturePlayback::dumpRegion(const SkRegion& region) const {
998 SkDebugf("region dump unimplemented\n");
999}
1000
1001int SkPicturePlayback::dumpDrawType(char* bufferPtr, char* buffer, DrawType drawType) {
1002 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1003 "k%s, ", DrawTypeToString(drawType));
1004}
1005
1006int SkPicturePlayback::dumpInt(char* bufferPtr, char* buffer, char* name) {
1007 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1008 "%s:%d, ", name, getInt());
1009}
1010
1011int SkPicturePlayback::dumpRect(char* bufferPtr, char* buffer, char* name) {
1012 const SkRect* rect = fReader.skipRect();
1013 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
reed@google.com82065d62011-02-07 15:30:46 +00001014 "%s:{l:%g t:%g r:%g b:%g}, ", name, SkScalarToFloat(rect.fLeft),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001015 SkScalarToFloat(rect.fTop),
1016 SkScalarToFloat(rect.fRight), SkScalarToFloat(rect.fBottom));
1017}
1018
1019int SkPicturePlayback::dumpPoint(char* bufferPtr, char* buffer, char* name) {
1020 SkPoint pt;
1021 getPoint(&pt);
1022 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
reed@google.com82065d62011-02-07 15:30:46 +00001023 "%s:{x:%g y:%g}, ", name, SkScalarToFloat(pt.fX),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001024 SkScalarToFloat(pt.fY));
1025}
1026
1027void SkPicturePlayback::dumpPointArray(char** bufferPtrPtr, char* buffer, int count) {
1028 char* bufferPtr = *bufferPtrPtr;
1029 const SkPoint* pts = (const SkPoint*)fReadStream.getAtPos();
1030 fReadStream.skip(sizeof(SkPoint) * count);
1031 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1032 "count:%d {", count);
1033 for (int index = 0; index < count; index++)
1034 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
reed@google.com82065d62011-02-07 15:30:46 +00001035 "{x:%g y:%g}, ", SkScalarToFloat(pts[index].fX),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001036 SkScalarToFloat(pts[index].fY));
1037 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1038 "} ");
1039 *bufferPtrPtr = bufferPtr;
1040}
1041
1042int SkPicturePlayback::dumpPtr(char* bufferPtr, char* buffer, char* name, void* ptr) {
1043 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1044 "%s:%p, ", name, ptr);
1045}
1046
1047int SkPicturePlayback::dumpRectPtr(char* bufferPtr, char* buffer, char* name) {
1048 char result;
1049 fReadStream.read(&result, sizeof(result));
1050 if (result)
1051 return dumpRect(bufferPtr, buffer, name);
1052 else
1053 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1054 "%s:NULL, ", name);
1055}
1056
1057int SkPicturePlayback::dumpScalar(char* bufferPtr, char* buffer, char* name) {
1058 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1059 "%s:%d, ", name, getScalar());
1060}
1061
1062void SkPicturePlayback::dumpText(char** bufferPtrPtr, char* buffer) {
1063 char* bufferPtr = *bufferPtrPtr;
1064 int length = getInt();
1065 bufferPtr += dumpDrawType(bufferPtr, buffer);
1066 fReadStream.skipToAlign4();
1067 char* text = (char*) fReadStream.getAtPos();
1068 fReadStream.skip(length);
1069 bufferPtr += dumpInt(bufferPtr, buffer, "length");
1070 int limit = DUMP_BUFFER_SIZE - (bufferPtr - buffer) - 2;
1071 length >>= 1;
1072 if (limit > length)
1073 limit = length;
1074 if (limit > 0) {
1075 *bufferPtr++ = '"';
1076 for (int index = 0; index < limit; index++) {
1077 *bufferPtr++ = *(unsigned short*) text;
1078 text += sizeof(unsigned short);
1079 }
1080 *bufferPtr++ = '"';
1081 }
1082 *bufferPtrPtr = bufferPtr;
1083}
1084
1085#define DUMP_DRAWTYPE(drawType) \
1086 bufferPtr += dumpDrawType(bufferPtr, buffer, drawType)
1087
1088#define DUMP_INT(name) \
1089 bufferPtr += dumpInt(bufferPtr, buffer, #name)
1090
1091#define DUMP_RECT_PTR(name) \
1092 bufferPtr += dumpRectPtr(bufferPtr, buffer, #name)
1093
1094#define DUMP_POINT(name) \
1095 bufferPtr += dumpRect(bufferPtr, buffer, #name)
1096
1097#define DUMP_RECT(name) \
1098 bufferPtr += dumpRect(bufferPtr, buffer, #name)
1099
1100#define DUMP_POINT_ARRAY(count) \
1101 dumpPointArray(&bufferPtr, buffer, count)
1102
1103#define DUMP_PTR(name, ptr) \
1104 bufferPtr += dumpPtr(bufferPtr, buffer, #name, (void*) ptr)
1105
1106#define DUMP_SCALAR(name) \
1107 bufferPtr += dumpScalar(bufferPtr, buffer, #name)
1108
1109#define DUMP_TEXT() \
1110 dumpText(&bufferPtr, buffer)
1111
1112void SkPicturePlayback::dumpStream() {
1113 SkDebugf("RecordStream stream = {\n");
1114 DrawType drawType;
1115 TextContainer text;
1116 fReadStream.rewind();
1117 char buffer[DUMP_BUFFER_SIZE], * bufferPtr;
1118 while (fReadStream.read(&drawType, sizeof(drawType))) {
1119 bufferPtr = buffer;
1120 DUMP_DRAWTYPE(drawType);
1121 switch (drawType) {
1122 case CLIP_PATH: {
1123 DUMP_PTR(SkPath, &getPath());
1124 DUMP_INT(SkRegion::Op);
1125 DUMP_INT(offsetToRestore);
1126 } break;
1127 case CLIP_REGION: {
1128 DUMP_PTR(SkRegion, &getRegion());
1129 DUMP_INT(SkRegion::Op);
1130 DUMP_INT(offsetToRestore);
1131 } break;
1132 case CLIP_RECT: {
1133 DUMP_RECT(rect);
1134 DUMP_INT(SkRegion::Op);
1135 DUMP_INT(offsetToRestore);
1136 } break;
1137 case CONCAT:
1138 DUMP_PTR(SkMatrix, getMatrix());
1139 break;
1140 case DRAW_BITMAP: {
1141 DUMP_PTR(SkPaint, getPaint());
1142 DUMP_PTR(SkBitmap, &getBitmap());
1143 DUMP_SCALAR(left);
1144 DUMP_SCALAR(top);
1145 } break;
1146 case DRAW_PAINT:
1147 DUMP_PTR(SkPaint, getPaint());
1148 break;
1149 case DRAW_PATH: {
1150 DUMP_PTR(SkPaint, getPaint());
1151 DUMP_PTR(SkPath, &getPath());
1152 } break;
1153 case DRAW_PICTURE: {
1154 DUMP_PTR(SkPicture, &getPicture());
1155 } break;
1156 case DRAW_POINTS: {
1157 DUMP_PTR(SkPaint, getPaint());
1158 (void)getInt(); // PointMode
1159 size_t count = getInt();
1160 fReadStream.skipToAlign4();
1161 DUMP_POINT_ARRAY(count);
1162 } break;
1163 case DRAW_POS_TEXT: {
1164 DUMP_PTR(SkPaint, getPaint());
1165 DUMP_TEXT();
1166 size_t points = getInt();
1167 fReadStream.skipToAlign4();
1168 DUMP_POINT_ARRAY(points);
1169 } break;
1170 case DRAW_POS_TEXT_H: {
1171 DUMP_PTR(SkPaint, getPaint());
1172 DUMP_TEXT();
1173 size_t points = getInt();
1174 fReadStream.skipToAlign4();
1175 DUMP_SCALAR(top);
1176 DUMP_SCALAR(bottom);
1177 DUMP_SCALAR(constY);
1178 DUMP_POINT_ARRAY(points);
1179 } break;
1180 case DRAW_RECT: {
1181 DUMP_PTR(SkPaint, getPaint());
1182 DUMP_RECT(rect);
1183 } break;
1184 case DRAW_SPRITE: {
1185 DUMP_PTR(SkPaint, getPaint());
1186 DUMP_PTR(SkBitmap, &getBitmap());
1187 DUMP_SCALAR(left);
1188 DUMP_SCALAR(top);
1189 } break;
1190 case DRAW_TEXT: {
1191 DUMP_PTR(SkPaint, getPaint());
1192 DUMP_TEXT();
1193 DUMP_SCALAR(x);
1194 DUMP_SCALAR(y);
1195 } break;
1196 case DRAW_TEXT_ON_PATH: {
1197 DUMP_PTR(SkPaint, getPaint());
1198 DUMP_TEXT();
1199 DUMP_PTR(SkPath, &getPath());
1200 DUMP_PTR(SkMatrix, getMatrix());
1201 } break;
1202 case RESTORE:
1203 break;
1204 case ROTATE:
1205 DUMP_SCALAR(rotate);
1206 break;
1207 case SAVE:
1208 DUMP_INT(SkCanvas::SaveFlags);
1209 break;
1210 case SAVE_LAYER: {
1211 DUMP_RECT_PTR(layer);
1212 DUMP_PTR(SkPaint, getPaint());
1213 DUMP_INT(SkCanvas::SaveFlags);
1214 } break;
1215 case SCALE: {
1216 DUMP_SCALAR(sx);
1217 DUMP_SCALAR(sy);
1218 } break;
1219 case SKEW: {
1220 DUMP_SCALAR(sx);
1221 DUMP_SCALAR(sy);
1222 } break;
1223 case TRANSLATE: {
1224 DUMP_SCALAR(dx);
1225 DUMP_SCALAR(dy);
1226 } break;
1227 default:
1228 SkASSERT(0);
1229 }
1230 SkDebugf("%s\n", buffer);
1231 }
1232}
1233
1234void SkPicturePlayback::dump() const {
1235 char pBuffer[DUMP_BUFFER_SIZE];
1236 char* bufferPtr = pBuffer;
1237 int index;
1238 if (fBitmapCount > 0)
1239 SkDebugf("// bitmaps (%d)\n", fBitmapCount);
1240 for (index = 0; index < fBitmapCount; index++) {
1241 const SkBitmap& bitmap = fBitmaps[index];
1242 dumpBitmap(bitmap);
1243 }
1244 if (fBitmapCount > 0)
reed@google.com82065d62011-02-07 15:30:46 +00001245 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001246 "Bitmaps bitmaps = {");
1247 for (index = 0; index < fBitmapCount; index++)
reed@google.com82065d62011-02-07 15:30:46 +00001248 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001249 "bitmap%p, ", &fBitmaps[index]);
1250 if (fBitmapCount > 0)
1251 SkDebugf("%s0};\n", pBuffer);
1252
1253 if (fMatrixCount > 0)
1254 SkDebugf("// matrices (%d)\n", fMatrixCount);
1255 for (index = 0; index < fMatrixCount; index++) {
1256 const SkMatrix& matrix = fMatrices[index];
1257 dumpMatrix(matrix);
1258 }
1259 bufferPtr = pBuffer;
1260 if (fMatrixCount > 0)
reed@google.com82065d62011-02-07 15:30:46 +00001261 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001262 "Matrices matrices = {");
1263 for (index = 0; index < fMatrixCount; index++)
reed@google.com82065d62011-02-07 15:30:46 +00001264 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001265 "matrix%p, ", &fMatrices[index]);
1266 if (fMatrixCount > 0)
1267 SkDebugf("%s0};\n", pBuffer);
1268
1269 if (fPaintCount > 0)
1270 SkDebugf("// paints (%d)\n", fPaintCount);
1271 for (index = 0; index < fPaintCount; index++) {
1272 const SkPaint& paint = fPaints[index];
1273 dumpPaint(paint);
1274 }
1275 bufferPtr = pBuffer;
1276 if (fPaintCount > 0)
reed@google.com82065d62011-02-07 15:30:46 +00001277 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001278 "Paints paints = {");
1279 for (index = 0; index < fPaintCount; index++)
reed@google.com82065d62011-02-07 15:30:46 +00001280 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001281 "paint%p, ", &fPaints[index]);
1282 if (fPaintCount > 0)
1283 SkDebugf("%s0};\n", pBuffer);
1284
1285 for (index = 0; index < fPathCount; index++) {
1286 const SkPath& path = fPaths[index];
1287 dumpPath(path);
1288 }
1289 bufferPtr = pBuffer;
1290 if (fPathCount > 0)
reed@google.com82065d62011-02-07 15:30:46 +00001291 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001292 "Paths paths = {");
1293 for (index = 0; index < fPathCount; index++)
reed@google.com82065d62011-02-07 15:30:46 +00001294 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001295 "path%p, ", &fPaths[index]);
1296 if (fPathCount > 0)
1297 SkDebugf("%s0};\n", pBuffer);
1298
1299 for (index = 0; index < fPictureCount; index++) {
1300 dumpPicture(*fPictureRefs[index]);
1301 }
1302 bufferPtr = pBuffer;
1303 if (fPictureCount > 0)
reed@google.com82065d62011-02-07 15:30:46 +00001304 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001305 "Pictures pictures = {");
1306 for (index = 0; index < fPictureCount; index++)
reed@google.com82065d62011-02-07 15:30:46 +00001307 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001308 "picture%p, ", fPictureRefs[index]);
1309 if (fPictureCount > 0)
1310 SkDebugf("%s0};\n", pBuffer);
1311
1312 for (index = 0; index < fRegionCount; index++) {
1313 const SkRegion& region = fRegions[index];
1314 dumpRegion(region);
1315 }
1316 bufferPtr = pBuffer;
1317 if (fRegionCount > 0)
reed@google.com82065d62011-02-07 15:30:46 +00001318 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001319 "Regions regions = {");
1320 for (index = 0; index < fRegionCount; index++)
reed@google.com82065d62011-02-07 15:30:46 +00001321 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
reed@android.com8a1c16f2008-12-17 15:59:43 +00001322 "region%p, ", &fRegions[index]);
1323 if (fRegionCount > 0)
1324 SkDebugf("%s0};\n", pBuffer);
1325
1326 const_cast<SkPicturePlayback*>(this)->dumpStream();
1327}
1328
1329#endif