• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2011 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 #include "SkPicturePlayback.h"
9 #include "SkPictureRecord.h"
10 #include "SkTypeface.h"
11 #include "SkOrderedReadBuffer.h"
12 #include "SkOrderedWriteBuffer.h"
13 #include <new>
14 #include "SkBBoxHierarchy.h"
15 #include "SkPictureStateTree.h"
16 #include "SkTSort.h"
17 
SafeCount(const T * obj)18 template <typename T> int SafeCount(const T* obj) {
19     return obj ? obj->count() : 0;
20 }
21 
22 /*  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 
SkPicturePlayback()27 SkPicturePlayback::SkPicturePlayback() {
28     this->init();
29 }
30 
SkPicturePlayback(const SkPictureRecord & record,bool deepCopy)31 SkPicturePlayback::SkPicturePlayback(const SkPictureRecord& record, bool deepCopy) {
32 #ifdef SK_DEBUG_SIZE
33     size_t overallBytes, bitmapBytes, matricesBytes,
34     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);
61 
62     SkDebugf("\n");
63 #endif
64 #ifdef SK_DEBUG_DUMP
65     record.dumpMatrices();
66     record.dumpPaints();
67 #endif
68 
69     record.validate();
70     const SkWriter32& writer = record.writeStream();
71     init();
72     if (writer.size() == 0) {
73         fOpData = SkData::NewEmpty();
74         return;
75     }
76 
77     fBoundingHierarchy = record.fBoundingHierarchy;
78     fStateTree = record.fStateTree;
79 
80     SkSafeRef(fBoundingHierarchy);
81     SkSafeRef(fStateTree);
82 
83     if (NULL != fBoundingHierarchy) {
84         fBoundingHierarchy->flushDeferredInserts();
85     }
86 
87     {
88         size_t size = writer.size();
89         void* buffer = sk_malloc_throw(size);
90         writer.flatten(buffer);
91         SkASSERT(!fOpData);
92         fOpData = SkData::NewFromMalloc(buffer, size);
93     }
94 
95     // copy over the refcnt dictionary to our reader
96     record.fFlattenableHeap.setupPlaybacks();
97 
98     fBitmaps = record.fBitmapHeap->extractBitmaps();
99     fMatrices = record.fMatrices.unflattenToArray();
100     fPaints = record.fPaints.unflattenToArray();
101     fRegions = record.fRegions.unflattenToArray();
102 
103     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     }
112 
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++) {
118             if (deepCopy) {
119                 fPictureRefs[i] = pictures[i]->clone();
120             } else {
121                 fPictureRefs[i] = pictures[i];
122                 fPictureRefs[i]->ref();
123             }
124         }
125     }
126 
127 #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 
needs_deep_copy(const SkPaint & paint)149 static 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 
SkPicturePlayback(const SkPicturePlayback & src,SkPictCopyInfo * deepCopyInfo)167 SkPicturePlayback::SkPicturePlayback(const SkPicturePlayback& src, SkPictCopyInfo* deepCopyInfo) {
168     this->init();
169 
170     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);
176 
177     fBoundingHierarchy = src.fBoundingHierarchy;
178     fStateTree = src.fStateTree;
179 
180     SkSafeRef(fBoundingHierarchy);
181     SkSafeRef(fStateTree);
182 
183     if (deepCopyInfo) {
184         int paintCount = SafeCount(src.fPaints);
185 
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              */
196             deepCopyInfo->paintData.setCount(paintCount);
197 
198             /* 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 
212             SkDEBUGCODE(int heapSize = SafeCount(fBitmapHeap.get());)
213             for (int i = 0; i < paintCount; i++) {
214                 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                 }
222             }
223             SkASSERT(SafeCount(fBitmapHeap.get()) == heapSize);
224 
225             // needed to create typeface playback
226             deepCopyInfo->controller.setupPlaybacks();
227             deepCopyInfo->initialized = true;
228         }
229 
230         fPaints = SkTRefArray<SkPaint>::Create(paintCount);
231         SkASSERT(deepCopyInfo->paintData.count() == paintCount);
232         SkBitmapHeap* bmHeap = deepCopyInfo->controller.getBitmapHeap();
233         SkTypefacePlayback* tfPlayback = deepCopyInfo->controller.getTypefacePlayback();
234         for (int i = 0; i < paintCount; i++) {
235             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             }
243         }
244 
245     } else {
246         fBitmaps = SkSafeRef(src.fBitmaps);
247         fPaints = SkSafeRef(src.fPaints);
248     }
249 
250     fPictureCount = src.fPictureCount;
251     fPictureRefs = SkNEW_ARRAY(SkPicture*, fPictureCount);
252     for (int i = 0; i < fPictureCount; i++) {
253         if (deepCopyInfo) {
254             fPictureRefs[i] = src.fPictureRefs[i]->clone();
255         } else {
256             fPictureRefs[i] = src.fPictureRefs[i];
257             fPictureRefs[i]->ref();
258         }
259     }
260 }
261 
init()262 void SkPicturePlayback::init() {
263     fBitmaps = NULL;
264     fMatrices = NULL;
265     fPaints = NULL;
266     fPictureRefs = NULL;
267     fRegions = NULL;
268     fPictureCount = 0;
269     fOpData = NULL;
270     fFactoryPlayback = NULL;
271     fBoundingHierarchy = NULL;
272     fStateTree = NULL;
273 }
274 
~SkPicturePlayback()275 SkPicturePlayback::~SkPicturePlayback() {
276     fOpData->unref();
277 
278     SkSafeUnref(fBitmaps);
279     SkSafeUnref(fMatrices);
280     SkSafeUnref(fPaints);
281     SkSafeUnref(fRegions);
282     SkSafeUnref(fBoundingHierarchy);
283     SkSafeUnref(fStateTree);
284 
285     for (int i = 0; i < fPictureCount; i++) {
286         fPictureRefs[i]->unref();
287     }
288     SkDELETE_ARRAY(fPictureRefs);
289 
290     SkDELETE(fFactoryPlayback);
291 }
292 
dumpSize() const293 void SkPicturePlayback::dumpSize() const {
294     SkDebugf("--- picture size: ops=%d bitmaps=%d [%d] matrices=%d [%d] paints=%d [%d] paths=%d regions=%d\n",
295              fOpData->size(),
296              SafeCount(fBitmaps), SafeCount(fBitmaps) * sizeof(SkBitmap),
297              SafeCount(fMatrices), SafeCount(fMatrices) * sizeof(SkMatrix),
298              SafeCount(fPaints), SafeCount(fPaints) * sizeof(SkPaint),
299              SafeCount(fPathHeap.get()),
300              SafeCount(fRegions));
301 }
302 
303 ///////////////////////////////////////////////////////////////////////////////
304 ///////////////////////////////////////////////////////////////////////////////
305 
306 #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')
310 
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')
313 // these are all inside the ARRAYS tag
314 #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', ' ')
319 
320 // Always write this guy last (with no length field afterwards)
321 #define PICT_EOF_TAG     SkSetFourByteTag('e', 'o', 'f', ' ')
322 
323 #include "SkStream.h"
324 
writeTagSize(SkOrderedWriteBuffer & buffer,uint32_t tag,uint32_t size)325 static void writeTagSize(SkOrderedWriteBuffer& buffer, uint32_t tag,
326                          uint32_t size) {
327     buffer.writeUInt(tag);
328     buffer.writeUInt(size);
329 }
330 
writeTagSize(SkWStream * stream,uint32_t tag,uint32_t size)331 static void writeTagSize(SkWStream* stream, uint32_t tag,
332                          uint32_t size) {
333     stream->write32(tag);
334     stream->write32(size);
335 }
336 
writeFactories(SkWStream * stream,const SkFactorySet & rec)337 static void writeFactories(SkWStream* stream, const SkFactorySet& rec) {
338     int count = rec.count();
339 
340     writeTagSize(stream, PICT_FACTORY_TAG, count);
341 
342     SkAutoSTMalloc<16, SkFlattenable::Factory> storage(count);
343     SkFlattenable::Factory* array = (SkFlattenable::Factory*)storage.get();
344     rec.copyToArray(array);
345 
346     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 
writeTypefaces(SkWStream * stream,const SkRefCntSet & rec)359 static void writeTypefaces(SkWStream* stream, const SkRefCntSet& rec) {
360     int count = rec.count();
361 
362     writeTagSize(stream, PICT_TYPEFACE_TAG, count);
363 
364     SkAutoSTMalloc<16, SkTypeface*> storage(count);
365     SkTypeface** array = (SkTypeface**)storage.get();
366     rec.copyToArray((SkRefCnt**)array);
367 
368     for (int i = 0; i < count; i++) {
369         array[i]->serialize(stream);
370     }
371 }
372 
flattenToBuffer(SkOrderedWriteBuffer & buffer) const373 void SkPicturePlayback::flattenToBuffer(SkOrderedWriteBuffer& buffer) const {
374     int i, n;
375 
376     if ((n = SafeCount(fBitmaps)) > 0) {
377         writeTagSize(buffer, PICT_BITMAP_BUFFER_TAG, n);
378         for (i = 0; i < n; i++) {
379             buffer.writeBitmap((*fBitmaps)[i]);
380         }
381     }
382 
383     if ((n = SafeCount(fMatrices)) > 0) {
384         writeTagSize(buffer, PICT_MATRIX_BUFFER_TAG, n);
385         for (i = 0; i < n; i++) {
386             buffer.writeMatrix((*fMatrices)[i]);
387         }
388 
389     }
390 
391     if ((n = SafeCount(fPaints)) > 0) {
392         writeTagSize(buffer, PICT_PAINT_BUFFER_TAG, n);
393         for (i = 0; i < n; i++) {
394             buffer.writePaint((*fPaints)[i]);
395         }
396     }
397 
398     if ((n = SafeCount(fPathHeap.get())) > 0) {
399         writeTagSize(buffer, PICT_PATH_BUFFER_TAG, n);
400         fPathHeap->flatten(buffer);
401     }
402 
403     if ((n = SafeCount(fRegions)) > 0) {
404         writeTagSize(buffer, PICT_REGION_BUFFER_TAG, n);
405         for (i = 0; i < n; i++) {
406             buffer.writeRegion((*fRegions)[i]);
407         }
408     }
409 }
410 
serialize(SkWStream * stream,SkSerializationHelpers::EncodeBitmap encoder) const411 void SkPicturePlayback::serialize(SkWStream* stream,
412                                   SkSerializationHelpers::EncodeBitmap encoder) const {
413     writeTagSize(stream, PICT_READER_TAG, fOpData->size());
414     stream->write(fOpData->bytes(), fOpData->size());
415 
416     if (fPictureCount > 0) {
417         writeTagSize(stream, PICT_PICTURE_TAG, fPictureCount);
418         for (int i = 0; i < fPictureCount; i++) {
419             fPictureRefs[i]->serialize(stream);
420         }
421     }
422 
423     // Write some of our data into a writebuffer, and then serialize that
424     // into our stream
425     {
426         SkRefCntSet  typefaceSet;
427         SkFactorySet factSet;
428 
429         SkOrderedWriteBuffer buffer(1024);
430 
431         buffer.setFlags(SkFlattenableWriteBuffer::kCrossProcess_Flag);
432         buffer.setTypefaceRecorder(&typefaceSet);
433         buffer.setFactoryRecorder(&factSet);
434         buffer.setBitmapEncoder(encoder);
435 
436         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);
446     }
447 
448     stream->write32(PICT_EOF_TAG);
449 }
450 
451 ///////////////////////////////////////////////////////////////////////////////
452 
453 /**
454  *  Return the corresponding SkFlattenableReadBuffer flags, given a set of
455  *  SkPictInfo flags.
456  */
pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags)457 static 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     };
466 
467     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 
parseStreamTag(SkStream * stream,const SkPictInfo & info,uint32_t tag,size_t size,SkSerializationHelpers::DecodeBitmap decoder)476 bool SkPicturePlayback::parseStreamTag(SkStream* stream, const SkPictInfo& info,
477                                        uint32_t tag, size_t size,
478                                        SkSerializationHelpers::DecodeBitmap decoder) {
479     /*
480      *  By the time we encounter BUFFER_SIZE_TAG, we need to have already seen
481      *  its dependents: FACTORY_TAG and TYPEFACE_TAG. These two are not required
482      *  but if they are present, they need to have been seen before the buffer.
483      *
484      *  We assert that if/when we see either of these, that we have not yet seen
485      *  the buffer tag, because if we have, then its too-late to deal with the
486      *  factories or typefaces.
487      */
488     bool haveBuffer = false;
489 
490     switch (tag) {
491         case PICT_READER_TAG: {
492             void* storage = sk_malloc_throw(size);
493             stream->read(storage, size);
494             SkASSERT(NULL == fOpData);
495             fOpData = SkData::NewFromMalloc(storage, size);
496         } break;
497         case PICT_FACTORY_TAG: {
498             SkASSERT(!haveBuffer);
499             fFactoryPlayback = SkNEW_ARGS(SkFactoryPlayback, (size));
500             for (size_t i = 0; i < size; i++) {
501                 SkString str;
502                 int len = stream->readPackedUInt();
503                 str.resize(len);
504                 stream->read(str.writable_str(), len);
505                 fFactoryPlayback->base()[i] = SkFlattenable::NameToFactory(str.c_str());
506             }
507         } break;
508         case PICT_TYPEFACE_TAG: {
509             SkASSERT(!haveBuffer);
510             fTFPlayback.setCount(size);
511             for (size_t i = 0; i < size; i++) {
512                 SkSafeUnref(fTFPlayback.set(i, SkTypeface::Deserialize(stream)));
513             }
514         } break;
515         case PICT_PICTURE_TAG: {
516             fPictureCount = size;
517             fPictureRefs = SkNEW_ARRAY(SkPicture*, fPictureCount);
518             for (int i = 0; i < fPictureCount; i++) {
519                 fPictureRefs[i] = SkNEW_ARGS(SkPicture, (stream));
520             }
521         } break;
522         case PICT_BUFFER_SIZE_TAG: {
523             SkAutoMalloc storage(size);
524             stream->read(storage.get(), size);
525 
526             SkOrderedReadBuffer buffer(storage.get(), size);
527             buffer.setFlags(pictInfoFlagsToReadBufferFlags(info.fFlags));
528 
529             fFactoryPlayback->setupBuffer(buffer);
530             fTFPlayback.setupBuffer(buffer);
531             buffer.setBitmapDecoder(decoder);
532 
533             while (!buffer.eof()) {
534                 tag = buffer.readUInt();
535                 size = buffer.readUInt();
536                 if (!this->parseBufferTag(buffer, tag, size)) {
537                     return false;
538                 }
539             }
540             haveBuffer = true;
541         } break;
542     }
543     return true;    // success
544 }
545 
parseBufferTag(SkOrderedReadBuffer & buffer,uint32_t tag,size_t size)546 bool SkPicturePlayback::parseBufferTag(SkOrderedReadBuffer& buffer,
547                                        uint32_t tag, size_t size) {
548     switch (tag) {
549         case PICT_BITMAP_BUFFER_TAG: {
550             fBitmaps = SkTRefArray<SkBitmap>::Create(size);
551             for (size_t i = 0; i < size; ++i) {
552                 SkBitmap* bm = &fBitmaps->writableAt(i);
553                 buffer.readBitmap(bm);
554                 bm->setImmutable();
555             }
556         } break;
557         case PICT_MATRIX_BUFFER_TAG:
558             fMatrices = SkTRefArray<SkMatrix>::Create(size);
559             for (size_t i = 0; i < size; ++i) {
560                 buffer.readMatrix(&fMatrices->writableAt(i));
561             }
562             break;
563         case PICT_PAINT_BUFFER_TAG: {
564             fPaints = SkTRefArray<SkPaint>::Create(size);
565             for (size_t i = 0; i < size; ++i) {
566                 buffer.readPaint(&fPaints->writableAt(i));
567             }
568         } break;
569         case PICT_PATH_BUFFER_TAG:
570             if (size > 0) {
571                 fPathHeap.reset(SkNEW_ARGS(SkPathHeap, (buffer)));
572             }
573             break;
574         case PICT_REGION_BUFFER_TAG: {
575             fRegions = SkTRefArray<SkRegion>::Create(size);
576             for (size_t i = 0; i < size; ++i) {
577                 buffer.readRegion(&fRegions->writableAt(i));
578             }
579         } break;
580     }
581     return true;    // success
582 }
583 
SkPicturePlayback(SkStream * stream,const SkPictInfo & info,bool * isValid,SkSerializationHelpers::DecodeBitmap decoder)584 SkPicturePlayback::SkPicturePlayback(SkStream* stream, const SkPictInfo& info,
585                                      bool* isValid, SkSerializationHelpers::DecodeBitmap decoder) {
586     this->init();
587 
588     *isValid = false;   // wait until we're done parsing to mark as true
589     for (;;) {
590         uint32_t tag = stream->readU32();
591         if (PICT_EOF_TAG == tag) {
592             break;
593         }
594 
595         uint32_t size = stream->readU32();
596         if (!this->parseStreamTag(stream, info, tag, size, decoder)) {
597             return; // we're invalid
598         }
599     }
600     *isValid = true;
601 }
602 
603 ///////////////////////////////////////////////////////////////////////////////
604 ///////////////////////////////////////////////////////////////////////////////
605 
606 #ifdef SPEW_CLIP_SKIPPING
607 struct SkipClipRec {
608     int     fCount;
609     size_t  fSize;
610 
SkipClipRecSkipClipRec611     SkipClipRec() {
612         fCount = 0;
613         fSize = 0;
614     }
615 
recordSkipSkipClipRec616     void recordSkip(size_t bytes) {
617         fCount += 1;
618         fSize += bytes;
619     }
620 };
621 #endif
622 
623 #ifdef SK_DEVELOPER
preDraw(size_t offset,int type)624 size_t SkPicturePlayback::preDraw(size_t offset, int type) {
625     return 0;
626 }
627 
postDraw(size_t offset)628 void SkPicturePlayback::postDraw(size_t offset) {
629 }
630 #endif
631 
draw(SkCanvas & canvas)632 void SkPicturePlayback::draw(SkCanvas& canvas) {
633 #ifdef ENABLE_TIME_DRAW
634     SkAutoTime  at("SkPicture::draw", 50);
635 #endif
636 
637 #ifdef SPEW_CLIP_SKIPPING
638     SkipClipRec skipRect, skipRRect, skipRegion, skipPath;
639 #endif
640 
641 #ifdef SK_BUILD_FOR_ANDROID
642     SkAutoMutexAcquire autoMutex(fDrawMutex);
643 #endif
644 
645     // kDrawComplete will be the signal that we have reached the end of
646     // the command stream
647     static const uint32_t kDrawComplete = SK_MaxU32;
648 
649     SkReader32 reader(fOpData->bytes(), fOpData->size());
650     TextContainer text;
651     SkTDArray<void*> results;
652 
653     if (NULL != fStateTree && NULL != fBoundingHierarchy) {
654         SkRect clipBounds;
655         if (canvas.getClipBounds(&clipBounds)) {
656             SkIRect query;
657             clipBounds.roundOut(&query);
658             fBoundingHierarchy->search(query, &results);
659             if (results.count() == 0) {
660                 return;
661             }
662             SkTQSort<SkPictureStateTree::Draw>(
663                 reinterpret_cast<SkPictureStateTree::Draw**>(results.begin()),
664                 reinterpret_cast<SkPictureStateTree::Draw**>(results.end()-1));
665         }
666     }
667 
668     SkPictureStateTree::Iterator it = (NULL == fStateTree) ?
669         SkPictureStateTree::Iterator() :
670         fStateTree->getIterator(results, &canvas);
671 
672     if (it.isValid()) {
673         uint32_t skipTo = it.draw();
674         if (kDrawComplete == skipTo) {
675             return;
676         }
677         reader.setOffset(skipTo);
678     }
679 
680     // Record this, so we can concat w/ it if we encounter a setMatrix()
681     SkMatrix initialMatrix = canvas.getTotalMatrix();
682 
683 #ifdef SK_BUILD_FOR_ANDROID
684     fAbortCurrentPlayback = false;
685 #endif
686 
687     while (!reader.eof()) {
688 #ifdef SK_BUILD_FOR_ANDROID
689         if (fAbortCurrentPlayback) {
690             return;
691         }
692 #endif
693 
694 #ifdef SK_DEVELOPER
695         size_t curOffset = reader.offset();
696 #endif
697         int type = reader.readInt();
698 #ifdef SK_DEVELOPER
699         size_t skipTo = this->preDraw(curOffset, type);
700         if (0 != skipTo) {
701             if (kDrawComplete == skipTo) {
702                 break;
703             }
704             reader.setOffset(skipTo);
705             continue;
706         }
707 #endif
708         switch (type) {
709             case CLIP_PATH: {
710                 const SkPath& path = getPath(reader);
711                 uint32_t packed = reader.readInt();
712                 SkRegion::Op op = ClipParams_unpackRegionOp(packed);
713                 bool doAA = ClipParams_unpackDoAA(packed);
714                 size_t offsetToRestore = reader.readInt();
715                 SkASSERT(!offsetToRestore || \
716                     offsetToRestore >= reader.offset());
717                 if (!canvas.clipPath(path, op, doAA) && offsetToRestore) {
718 #ifdef SPEW_CLIP_SKIPPING
719                     skipPath.recordSkip(offsetToRestore - reader.offset());
720 #endif
721                     reader.setOffset(offsetToRestore);
722                 }
723             } break;
724             case CLIP_REGION: {
725                 const SkRegion& region = getRegion(reader);
726                 uint32_t packed = reader.readInt();
727                 SkRegion::Op op = ClipParams_unpackRegionOp(packed);
728                 size_t offsetToRestore = reader.readInt();
729                 SkASSERT(!offsetToRestore || \
730                     offsetToRestore >= reader.offset());
731                 if (!canvas.clipRegion(region, op) && offsetToRestore) {
732 #ifdef SPEW_CLIP_SKIPPING
733                     skipRegion.recordSkip(offsetToRestore - reader.offset());
734 #endif
735                     reader.setOffset(offsetToRestore);
736                 }
737             } break;
738             case CLIP_RECT: {
739                 const SkRect& rect = reader.skipT<SkRect>();
740                 uint32_t packed = reader.readInt();
741                 SkRegion::Op op = ClipParams_unpackRegionOp(packed);
742                 bool doAA = ClipParams_unpackDoAA(packed);
743                 size_t offsetToRestore = reader.readInt();
744                 SkASSERT(!offsetToRestore || \
745                          offsetToRestore >= reader.offset());
746                 if (!canvas.clipRect(rect, op, doAA) && offsetToRestore) {
747 #ifdef SPEW_CLIP_SKIPPING
748                     skipRect.recordSkip(offsetToRestore - reader.offset());
749 #endif
750                     reader.setOffset(offsetToRestore);
751                 }
752             } break;
753             case CLIP_RRECT: {
754                 SkRRect rrect;
755                 reader.readRRect(&rrect);
756                 uint32_t packed = reader.readInt();
757                 SkRegion::Op op = ClipParams_unpackRegionOp(packed);
758                 bool doAA = ClipParams_unpackDoAA(packed);
759                 size_t offsetToRestore = reader.readInt();
760                 SkASSERT(!offsetToRestore || \
761                          offsetToRestore >= reader.offset());
762                 if (!canvas.clipRRect(rrect, op, doAA) && offsetToRestore) {
763 #ifdef SPEW_CLIP_SKIPPING
764                     skipRRect.recordSkip(offsetToRestore - reader.offset());
765 #endif
766                     reader.setOffset(offsetToRestore);
767                 }
768             } break;
769             case CONCAT:
770                 canvas.concat(*getMatrix(reader));
771                 break;
772             case DRAW_BITMAP: {
773                 const SkPaint* paint = getPaint(reader);
774                 const SkBitmap& bitmap = getBitmap(reader);
775                 const SkPoint& loc = reader.skipT<SkPoint>();
776                 canvas.drawBitmap(bitmap, loc.fX, loc.fY, paint);
777             } break;
778             case DRAW_BITMAP_RECT_TO_RECT: {
779                 const SkPaint* paint = getPaint(reader);
780                 const SkBitmap& bitmap = getBitmap(reader);
781                 const SkRect* src = this->getRectPtr(reader);   // may be null
782                 const SkRect& dst = reader.skipT<SkRect>();     // required
783                 canvas.drawBitmapRectToRect(bitmap, src, dst, paint);
784             } break;
785             case DRAW_BITMAP_MATRIX: {
786                 const SkPaint* paint = getPaint(reader);
787                 const SkBitmap& bitmap = getBitmap(reader);
788                 const SkMatrix* matrix = getMatrix(reader);
789                 canvas.drawBitmapMatrix(bitmap, *matrix, paint);
790             } break;
791             case DRAW_BITMAP_NINE: {
792                 const SkPaint* paint = getPaint(reader);
793                 const SkBitmap& bitmap = getBitmap(reader);
794                 const SkIRect& src = reader.skipT<SkIRect>();
795                 const SkRect& dst = reader.skipT<SkRect>();
796                 canvas.drawBitmapNine(bitmap, src, dst, paint);
797             } break;
798             case DRAW_CLEAR:
799                 canvas.clear(reader.readInt());
800                 break;
801             case DRAW_DATA: {
802                 size_t length = reader.readInt();
803                 canvas.drawData(reader.skip(length), length);
804                 // skip handles padding the read out to a multiple of 4
805             } break;
806             case DRAW_OVAL: {
807                 const SkPaint& paint = *getPaint(reader);
808                 canvas.drawOval(reader.skipT<SkRect>(), paint);
809             } break;
810             case DRAW_PAINT:
811                 canvas.drawPaint(*getPaint(reader));
812                 break;
813             case DRAW_PATH: {
814                 const SkPaint& paint = *getPaint(reader);
815                 canvas.drawPath(getPath(reader), paint);
816             } break;
817             case DRAW_PICTURE:
818                 canvas.drawPicture(getPicture(reader));
819                 break;
820             case DRAW_POINTS: {
821                 const SkPaint& paint = *getPaint(reader);
822                 SkCanvas::PointMode mode = (SkCanvas::PointMode)reader.readInt();
823                 size_t count = reader.readInt();
824                 const SkPoint* pts = (const SkPoint*)reader.skip(sizeof(SkPoint) * count);
825                 canvas.drawPoints(mode, count, pts, paint);
826             } break;
827             case DRAW_POS_TEXT: {
828                 const SkPaint& paint = *getPaint(reader);
829                 getText(reader, &text);
830                 size_t points = reader.readInt();
831                 const SkPoint* pos = (const SkPoint*)reader.skip(points * sizeof(SkPoint));
832                 canvas.drawPosText(text.text(), text.length(), pos, paint);
833             } break;
834             case DRAW_POS_TEXT_TOP_BOTTOM: {
835                 const SkPaint& paint = *getPaint(reader);
836                 getText(reader, &text);
837                 size_t points = reader.readInt();
838                 const SkPoint* pos = (const SkPoint*)reader.skip(points * sizeof(SkPoint));
839                 const SkScalar top = reader.readScalar();
840                 const SkScalar bottom = reader.readScalar();
841                 if (!canvas.quickRejectY(top, bottom)) {
842                     canvas.drawPosText(text.text(), text.length(), pos, paint);
843                 }
844             } break;
845             case DRAW_POS_TEXT_H: {
846                 const SkPaint& paint = *getPaint(reader);
847                 getText(reader, &text);
848                 size_t xCount = reader.readInt();
849                 const SkScalar constY = reader.readScalar();
850                 const SkScalar* xpos = (const SkScalar*)reader.skip(xCount * sizeof(SkScalar));
851                 canvas.drawPosTextH(text.text(), text.length(), xpos, constY,
852                                     paint);
853             } break;
854             case DRAW_POS_TEXT_H_TOP_BOTTOM: {
855                 const SkPaint& paint = *getPaint(reader);
856                 getText(reader, &text);
857                 size_t xCount = reader.readInt();
858                 const SkScalar* xpos = (const SkScalar*)reader.skip((3 + xCount) * sizeof(SkScalar));
859                 const SkScalar top = *xpos++;
860                 const SkScalar bottom = *xpos++;
861                 const SkScalar constY = *xpos++;
862                 if (!canvas.quickRejectY(top, bottom)) {
863                     canvas.drawPosTextH(text.text(), text.length(), xpos,
864                                         constY, paint);
865                 }
866             } break;
867             case DRAW_RECT: {
868                 const SkPaint& paint = *getPaint(reader);
869                 canvas.drawRect(reader.skipT<SkRect>(), paint);
870             } break;
871             case DRAW_RRECT: {
872                 const SkPaint& paint = *getPaint(reader);
873                 SkRRect rrect;
874                 canvas.drawRRect(*reader.readRRect(&rrect), paint);
875             } break;
876             case DRAW_SPRITE: {
877                 const SkPaint* paint = getPaint(reader);
878                 const SkBitmap& bitmap = getBitmap(reader);
879                 int left = reader.readInt();
880                 int top = reader.readInt();
881                 canvas.drawSprite(bitmap, left, top, paint);
882             } break;
883             case DRAW_TEXT: {
884                 const SkPaint& paint = *getPaint(reader);
885                 getText(reader, &text);
886                 SkScalar x = reader.readScalar();
887                 SkScalar y = reader.readScalar();
888                 canvas.drawText(text.text(), text.length(), x, y, paint);
889             } break;
890             case DRAW_TEXT_TOP_BOTTOM: {
891                 const SkPaint& paint = *getPaint(reader);
892                 getText(reader, &text);
893                 const SkScalar* ptr = (const SkScalar*)reader.skip(4 * sizeof(SkScalar));
894                 // ptr[0] == x
895                 // ptr[1] == y
896                 // ptr[2] == top
897                 // ptr[3] == bottom
898                 if (!canvas.quickRejectY(ptr[2], ptr[3])) {
899                     canvas.drawText(text.text(), text.length(), ptr[0], ptr[1],
900                                     paint);
901                 }
902             } break;
903             case DRAW_TEXT_ON_PATH: {
904                 const SkPaint& paint = *getPaint(reader);
905                 getText(reader, &text);
906                 const SkPath& path = getPath(reader);
907                 const SkMatrix* matrix = getMatrix(reader);
908                 canvas.drawTextOnPath(text.text(), text.length(), path,
909                                       matrix, paint);
910             } break;
911             case DRAW_VERTICES: {
912                 const SkPaint& paint = *getPaint(reader);
913                 DrawVertexFlags flags = (DrawVertexFlags)reader.readInt();
914                 SkCanvas::VertexMode vmode = (SkCanvas::VertexMode)reader.readInt();
915                 int vCount = reader.readInt();
916                 const SkPoint* verts = (const SkPoint*)reader.skip(
917                                                     vCount * sizeof(SkPoint));
918                 const SkPoint* texs = NULL;
919                 const SkColor* colors = NULL;
920                 const uint16_t* indices = NULL;
921                 int iCount = 0;
922                 if (flags & DRAW_VERTICES_HAS_TEXS) {
923                     texs = (const SkPoint*)reader.skip(
924                                                     vCount * sizeof(SkPoint));
925                 }
926                 if (flags & DRAW_VERTICES_HAS_COLORS) {
927                     colors = (const SkColor*)reader.skip(
928                                                     vCount * sizeof(SkColor));
929                 }
930                 if (flags & DRAW_VERTICES_HAS_INDICES) {
931                     iCount = reader.readInt();
932                     indices = (const uint16_t*)reader.skip(
933                                                     iCount * sizeof(uint16_t));
934                 }
935                 canvas.drawVertices(vmode, vCount, verts, texs, colors, NULL,
936                                     indices, iCount, paint);
937             } break;
938             case RESTORE:
939                 canvas.restore();
940                 break;
941             case ROTATE:
942                 canvas.rotate(reader.readScalar());
943                 break;
944             case SAVE:
945                 canvas.save((SkCanvas::SaveFlags) reader.readInt());
946                 break;
947             case SAVE_LAYER: {
948                 const SkRect* boundsPtr = getRectPtr(reader);
949                 const SkPaint* paint = getPaint(reader);
950                 canvas.saveLayer(boundsPtr, paint, (SkCanvas::SaveFlags) reader.readInt());
951                 } break;
952             case SCALE: {
953                 SkScalar sx = reader.readScalar();
954                 SkScalar sy = reader.readScalar();
955                 canvas.scale(sx, sy);
956             } break;
957             case SET_MATRIX: {
958                 SkMatrix matrix;
959                 matrix.setConcat(initialMatrix, *getMatrix(reader));
960                 canvas.setMatrix(matrix);
961             } break;
962             case SKEW: {
963                 SkScalar sx = reader.readScalar();
964                 SkScalar sy = reader.readScalar();
965                 canvas.skew(sx, sy);
966             } break;
967             case TRANSLATE: {
968                 SkScalar dx = reader.readScalar();
969                 SkScalar dy = reader.readScalar();
970                 canvas.translate(dx, dy);
971             } break;
972             default:
973                 SkASSERT(0);
974         }
975 
976 #ifdef SK_DEVELOPER
977         this->postDraw(curOffset);
978 #endif
979 
980         if (it.isValid()) {
981             uint32_t skipTo = it.draw();
982             if (kDrawComplete == skipTo) {
983                 break;
984             }
985             reader.setOffset(skipTo);
986         }
987     }
988 
989 #ifdef SPEW_CLIP_SKIPPING
990     {
991         size_t size =  skipRect.fSize + skipRRect.fSize + skipPath.fSize + skipRegion.fSize;
992         SkDebugf("--- Clip skips %d%% rect:%d rrect:%d path:%d rgn:%d\n",
993              size * 100 / reader.offset(), skipRect.fCount, skipRRect.fCount,
994                  skipPath.fCount, skipRegion.fCount);
995     }
996 #endif
997 //    this->dumpSize();
998 }
999 
1000 ///////////////////////////////////////////////////////////////////////////////
1001 
1002 #ifdef SK_DEBUG_SIZE
size(size_t * sizePtr)1003 int SkPicturePlayback::size(size_t* sizePtr) {
1004     int objects = bitmaps(sizePtr);
1005     objects += paints(sizePtr);
1006     objects += paths(sizePtr);
1007     objects += pictures(sizePtr);
1008     objects += regions(sizePtr);
1009     *sizePtr = fOpData.size();
1010     return objects;
1011 }
1012 
bitmaps(size_t * size)1013 int SkPicturePlayback::bitmaps(size_t* size) {
1014     size_t result = 0;
1015     for (int index = 0; index < fBitmapCount; index++) {
1016      //   const SkBitmap& bitmap = fBitmaps[index];
1017         result += sizeof(SkBitmap); // bitmap->size();
1018     }
1019     *size = result;
1020     return fBitmapCount;
1021 }
1022 
paints(size_t * size)1023 int SkPicturePlayback::paints(size_t* size) {
1024     size_t result = 0;
1025     for (int index = 0; index < fPaintCount; index++) {
1026     //    const SkPaint& paint = fPaints[index];
1027         result += sizeof(SkPaint); // paint->size();
1028     }
1029     *size = result;
1030     return fPaintCount;
1031 }
1032 
paths(size_t * size)1033 int SkPicturePlayback::paths(size_t* size) {
1034     size_t result = 0;
1035     for (int index = 0; index < fPathCount; index++) {
1036         const SkPath& path = fPaths[index];
1037         result += path.flatten(NULL);
1038     }
1039     *size = result;
1040     return fPathCount;
1041 }
1042 
regions(size_t * size)1043 int SkPicturePlayback::regions(size_t* size) {
1044     size_t result = 0;
1045     for (int index = 0; index < fRegionCount; index++) {
1046     //    const SkRegion& region = fRegions[index];
1047         result += sizeof(SkRegion); // region->size();
1048     }
1049     *size = result;
1050     return fRegionCount;
1051 }
1052 #endif
1053 
1054 #ifdef SK_DEBUG_DUMP
dumpBitmap(const SkBitmap & bitmap) const1055 void SkPicturePlayback::dumpBitmap(const SkBitmap& bitmap) const {
1056     char pBuffer[DUMP_BUFFER_SIZE];
1057     char* bufferPtr = pBuffer;
1058     bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1059         "BitmapData bitmap%p = {", &bitmap);
1060     bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1061         "{kWidth, %d}, ", bitmap.width());
1062     bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1063         "{kHeight, %d}, ", bitmap.height());
1064     bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1065         "{kRowBytes, %d}, ", bitmap.rowBytes());
1066 //        start here;
1067     SkDebugf("%s{0}};\n", pBuffer);
1068 }
1069 
dumpMatrix(const SkMatrix & matrix) const1070 void dumpMatrix(const SkMatrix& matrix) const {
1071     SkMatrix defaultMatrix;
1072     defaultMatrix.reset();
1073     char pBuffer[DUMP_BUFFER_SIZE];
1074     char* bufferPtr = pBuffer;
1075     bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1076         "MatrixData matrix%p = {", &matrix);
1077     SkScalar scaleX = matrix.getScaleX();
1078     if (scaleX != defaultMatrix.getScaleX())
1079         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1080             "{kScaleX, %g}, ", SkScalarToFloat(scaleX));
1081     SkScalar scaleY = matrix.getScaleY();
1082     if (scaleY != defaultMatrix.getScaleY())
1083         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1084             "{kScaleY, %g}, ", SkScalarToFloat(scaleY));
1085     SkScalar skewX = matrix.getSkewX();
1086     if (skewX != defaultMatrix.getSkewX())
1087         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1088             "{kSkewX, %g}, ", SkScalarToFloat(skewX));
1089     SkScalar skewY = matrix.getSkewY();
1090     if (skewY != defaultMatrix.getSkewY())
1091         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1092             "{kSkewY, %g}, ", SkScalarToFloat(skewY));
1093     SkScalar translateX = matrix.getTranslateX();
1094     if (translateX != defaultMatrix.getTranslateX())
1095         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1096             "{kTranslateX, %g}, ", SkScalarToFloat(translateX));
1097     SkScalar translateY = matrix.getTranslateY();
1098     if (translateY != defaultMatrix.getTranslateY())
1099         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1100             "{kTranslateY, %g}, ", SkScalarToFloat(translateY));
1101     SkScalar perspX = matrix.getPerspX();
1102     if (perspX != defaultMatrix.getPerspX())
1103         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1104             "{kPerspX, %g}, ", SkFractToFloat(perspX));
1105     SkScalar perspY = matrix.getPerspY();
1106     if (perspY != defaultMatrix.getPerspY())
1107         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1108             "{kPerspY, %g}, ", SkFractToFloat(perspY));
1109     SkDebugf("%s{0}};\n", pBuffer);
1110 }
1111 
dumpPaint(const SkPaint & paint) const1112 void dumpPaint(const SkPaint& paint) const {
1113     SkPaint defaultPaint;
1114     char pBuffer[DUMP_BUFFER_SIZE];
1115     char* bufferPtr = pBuffer;
1116     bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1117         "PaintPointers paintPtrs%p = {", &paint);
1118     const SkTypeface* typeface = paint.getTypeface();
1119     if (typeface != defaultPaint.getTypeface())
1120         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1121             "{kTypeface, %p}, ", typeface);
1122     const SkPathEffect* pathEffect = paint.getPathEffect();
1123     if (pathEffect != defaultPaint.getPathEffect())
1124         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1125             "{kPathEffect, %p}, ", pathEffect);
1126     const SkShader* shader = paint.getShader();
1127     if (shader != defaultPaint.getShader())
1128         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1129             "{kShader, %p}, ", shader);
1130     const SkXfermode* xfermode = paint.getXfermode();
1131     if (xfermode != defaultPaint.getXfermode())
1132         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1133             "{kXfermode, %p}, ", xfermode);
1134     const SkMaskFilter* maskFilter = paint.getMaskFilter();
1135     if (maskFilter != defaultPaint.getMaskFilter())
1136         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1137             "{kMaskFilter, %p}, ", maskFilter);
1138     const SkColorFilter* colorFilter = paint.getColorFilter();
1139     if (colorFilter != defaultPaint.getColorFilter())
1140         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1141             "{kColorFilter, %p}, ", colorFilter);
1142     const SkRasterizer* rasterizer = paint.getRasterizer();
1143     if (rasterizer != defaultPaint.getRasterizer())
1144         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1145             "{kRasterizer, %p}, ", rasterizer);
1146     const SkDrawLooper* drawLooper = paint.getLooper();
1147     if (drawLooper != defaultPaint.getLooper())
1148         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1149             "{kDrawLooper, %p}, ", drawLooper);
1150     SkDebugf("%s{0}};\n", pBuffer);
1151     bufferPtr = pBuffer;
1152     bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1153         "PaintScalars paintScalars%p = {", &paint);
1154     SkScalar textSize = paint.getTextSize();
1155     if (textSize != defaultPaint.getTextSize())
1156         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1157             "{kTextSize, %g}, ", SkScalarToFloat(textSize));
1158     SkScalar textScaleX = paint.getTextScaleX();
1159     if (textScaleX != defaultPaint.getTextScaleX())
1160         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1161             "{kTextScaleX, %g}, ", SkScalarToFloat(textScaleX));
1162     SkScalar textSkewX = paint.getTextSkewX();
1163     if (textSkewX != defaultPaint.getTextSkewX())
1164         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1165             "{kTextSkewX, %g}, ", SkScalarToFloat(textSkewX));
1166     SkScalar strokeWidth = paint.getStrokeWidth();
1167     if (strokeWidth != defaultPaint.getStrokeWidth())
1168         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1169             "{kStrokeWidth, %g}, ", SkScalarToFloat(strokeWidth));
1170     SkScalar strokeMiter = paint.getStrokeMiter();
1171     if (strokeMiter != defaultPaint.getStrokeMiter())
1172         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1173             "{kStrokeMiter, %g}, ", SkScalarToFloat(strokeMiter));
1174     SkDebugf("%s{0}};\n", pBuffer);
1175     bufferPtr = pBuffer;
1176     bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1177         "PaintInts = paintInts%p = {", &paint);
1178     unsigned color = paint.getColor();
1179     if (color != defaultPaint.getColor())
1180         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1181             "{kColor, 0x%x}, ", color);
1182     unsigned flags = paint.getFlags();
1183     if (flags != defaultPaint.getFlags())
1184         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1185             "{kFlags, 0x%x}, ", flags);
1186     int align = paint.getTextAlign();
1187     if (align != defaultPaint.getTextAlign())
1188         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1189             "{kAlign, 0x%x}, ", align);
1190     int strokeCap = paint.getStrokeCap();
1191     if (strokeCap != defaultPaint.getStrokeCap())
1192         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1193             "{kStrokeCap, 0x%x}, ", strokeCap);
1194     int strokeJoin = paint.getStrokeJoin();
1195     if (strokeJoin != defaultPaint.getStrokeJoin())
1196         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1197             "{kAlign, 0x%x}, ", strokeJoin);
1198     int style = paint.getStyle();
1199     if (style != defaultPaint.getStyle())
1200         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1201             "{kStyle, 0x%x}, ", style);
1202     int textEncoding = paint.getTextEncoding();
1203     if (textEncoding != defaultPaint.getTextEncoding())
1204         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1205             "{kTextEncoding, 0x%x}, ", textEncoding);
1206     SkDebugf("%s{0}};\n", pBuffer);
1207 
1208     SkDebugf("PaintData paint%p = {paintPtrs%p, paintScalars%p, paintInts%p};\n",
1209         &paint, &paint, &paint, &paint);
1210 }
1211 
dumpPath(const SkPath & path) const1212 void SkPicturePlayback::dumpPath(const SkPath& path) const {
1213     SkDebugf("path dump unimplemented\n");
1214 }
1215 
dumpPicture(const SkPicture & picture) const1216 void SkPicturePlayback::dumpPicture(const SkPicture& picture) const {
1217     SkDebugf("picture dump unimplemented\n");
1218 }
1219 
dumpRegion(const SkRegion & region) const1220 void SkPicturePlayback::dumpRegion(const SkRegion& region) const {
1221     SkDebugf("region dump unimplemented\n");
1222 }
1223 
dumpDrawType(char * bufferPtr,char * buffer,DrawType drawType)1224 int SkPicturePlayback::dumpDrawType(char* bufferPtr, char* buffer, DrawType drawType) {
1225     return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1226         "k%s, ", DrawTypeToString(drawType));
1227 }
1228 
dumpInt(char * bufferPtr,char * buffer,char * name)1229 int SkPicturePlayback::dumpInt(char* bufferPtr, char* buffer, char* name) {
1230     return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1231         "%s:%d, ", name, getInt());
1232 }
1233 
dumpRect(char * bufferPtr,char * buffer,char * name)1234 int SkPicturePlayback::dumpRect(char* bufferPtr, char* buffer, char* name) {
1235     const SkRect* rect = fReader.skipRect();
1236     return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1237         "%s:{l:%g t:%g r:%g b:%g}, ", name, SkScalarToFloat(rect.fLeft),
1238         SkScalarToFloat(rect.fTop),
1239         SkScalarToFloat(rect.fRight), SkScalarToFloat(rect.fBottom));
1240 }
1241 
dumpPoint(char * bufferPtr,char * buffer,char * name)1242 int SkPicturePlayback::dumpPoint(char* bufferPtr, char* buffer, char* name) {
1243     SkPoint pt;
1244     getPoint(&pt);
1245     return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1246         "%s:{x:%g y:%g}, ", name, SkScalarToFloat(pt.fX),
1247         SkScalarToFloat(pt.fY));
1248 }
1249 
dumpPointArray(char ** bufferPtrPtr,char * buffer,int count)1250 void SkPicturePlayback::dumpPointArray(char** bufferPtrPtr, char* buffer, int count) {
1251     char* bufferPtr = *bufferPtrPtr;
1252     const SkPoint* pts = (const SkPoint*)fReadStream.getAtPos();
1253     fReadStream.skip(sizeof(SkPoint) * count);
1254     bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1255         "count:%d {", count);
1256     for (int index = 0; index < count; index++)
1257         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1258         "{x:%g y:%g}, ", SkScalarToFloat(pts[index].fX),
1259         SkScalarToFloat(pts[index].fY));
1260     bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1261         "} ");
1262     *bufferPtrPtr = bufferPtr;
1263 }
1264 
dumpPtr(char * bufferPtr,char * buffer,char * name,void * ptr)1265 int SkPicturePlayback::dumpPtr(char* bufferPtr, char* buffer, char* name, void* ptr) {
1266     return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1267         "%s:%p, ", name, ptr);
1268 }
1269 
dumpRectPtr(char * bufferPtr,char * buffer,char * name)1270 int SkPicturePlayback::dumpRectPtr(char* bufferPtr, char* buffer, char* name) {
1271     char result;
1272     fReadStream.read(&result, sizeof(result));
1273     if (result)
1274         return dumpRect(bufferPtr, buffer, name);
1275     else
1276         return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1277             "%s:NULL, ", name);
1278 }
1279 
dumpScalar(char * bufferPtr,char * buffer,char * name)1280 int SkPicturePlayback::dumpScalar(char* bufferPtr, char* buffer, char* name) {
1281     return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1282         "%s:%d, ", name, getScalar());
1283 }
1284 
dumpText(char ** bufferPtrPtr,char * buffer)1285 void SkPicturePlayback::dumpText(char** bufferPtrPtr, char* buffer) {
1286     char* bufferPtr = *bufferPtrPtr;
1287     int length = getInt();
1288     bufferPtr += dumpDrawType(bufferPtr, buffer);
1289     fReadStream.skipToAlign4();
1290     char* text = (char*) fReadStream.getAtPos();
1291     fReadStream.skip(length);
1292     bufferPtr += dumpInt(bufferPtr, buffer, "length");
1293     int limit = DUMP_BUFFER_SIZE - (bufferPtr - buffer) - 2;
1294     length >>= 1;
1295     if (limit > length)
1296         limit = length;
1297     if (limit > 0) {
1298         *bufferPtr++ = '"';
1299         for (int index = 0; index < limit; index++) {
1300             *bufferPtr++ = *(unsigned short*) text;
1301             text += sizeof(unsigned short);
1302         }
1303         *bufferPtr++ = '"';
1304     }
1305     *bufferPtrPtr = bufferPtr;
1306 }
1307 
1308 #define DUMP_DRAWTYPE(drawType) \
1309     bufferPtr += dumpDrawType(bufferPtr, buffer, drawType)
1310 
1311 #define DUMP_INT(name) \
1312     bufferPtr += dumpInt(bufferPtr, buffer, #name)
1313 
1314 #define DUMP_RECT_PTR(name) \
1315     bufferPtr += dumpRectPtr(bufferPtr, buffer, #name)
1316 
1317 #define DUMP_POINT(name) \
1318     bufferPtr += dumpRect(bufferPtr, buffer, #name)
1319 
1320 #define DUMP_RECT(name) \
1321     bufferPtr += dumpRect(bufferPtr, buffer, #name)
1322 
1323 #define DUMP_POINT_ARRAY(count) \
1324     dumpPointArray(&bufferPtr, buffer, count)
1325 
1326 #define DUMP_PTR(name, ptr) \
1327     bufferPtr += dumpPtr(bufferPtr, buffer, #name, (void*) ptr)
1328 
1329 #define DUMP_SCALAR(name) \
1330     bufferPtr += dumpScalar(bufferPtr, buffer, #name)
1331 
1332 #define DUMP_TEXT() \
1333     dumpText(&bufferPtr, buffer)
1334 
dumpStream()1335 void SkPicturePlayback::dumpStream() {
1336     SkDebugf("RecordStream stream = {\n");
1337     DrawType drawType;
1338     TextContainer text;
1339     fReadStream.rewind();
1340     char buffer[DUMP_BUFFER_SIZE], * bufferPtr;
1341     while (fReadStream.read(&drawType, sizeof(drawType))) {
1342         bufferPtr = buffer;
1343         DUMP_DRAWTYPE(drawType);
1344         switch (drawType) {
1345             case CLIP_PATH: {
1346                 DUMP_PTR(SkPath, &getPath());
1347                 DUMP_INT(SkRegion::Op);
1348                 DUMP_INT(offsetToRestore);
1349                 } break;
1350             case CLIP_REGION: {
1351                 DUMP_PTR(SkRegion, &getRegion());
1352                 DUMP_INT(SkRegion::Op);
1353                 DUMP_INT(offsetToRestore);
1354             } break;
1355             case CLIP_RECT: {
1356                 DUMP_RECT(rect);
1357                 DUMP_INT(SkRegion::Op);
1358                 DUMP_INT(offsetToRestore);
1359                 } break;
1360             case CONCAT:
1361                 DUMP_PTR(SkMatrix, getMatrix());
1362                 break;
1363             case DRAW_BITMAP: {
1364                 DUMP_PTR(SkPaint, getPaint());
1365                 DUMP_PTR(SkBitmap, &getBitmap());
1366                 DUMP_SCALAR(left);
1367                 DUMP_SCALAR(top);
1368                 } break;
1369             case DRAW_PAINT:
1370                 DUMP_PTR(SkPaint, getPaint());
1371                 break;
1372             case DRAW_PATH: {
1373                 DUMP_PTR(SkPaint, getPaint());
1374                 DUMP_PTR(SkPath, &getPath());
1375                 } break;
1376             case DRAW_PICTURE: {
1377                 DUMP_PTR(SkPicture, &getPicture());
1378                 } break;
1379             case DRAW_POINTS: {
1380                 DUMP_PTR(SkPaint, getPaint());
1381                 (void)getInt(); // PointMode
1382                 size_t count = getInt();
1383                 fReadStream.skipToAlign4();
1384                 DUMP_POINT_ARRAY(count);
1385                 } break;
1386             case DRAW_POS_TEXT: {
1387                 DUMP_PTR(SkPaint, getPaint());
1388                 DUMP_TEXT();
1389                 size_t points = getInt();
1390                 fReadStream.skipToAlign4();
1391                 DUMP_POINT_ARRAY(points);
1392                 } break;
1393             case DRAW_POS_TEXT_H: {
1394                 DUMP_PTR(SkPaint, getPaint());
1395                 DUMP_TEXT();
1396                 size_t points = getInt();
1397                 fReadStream.skipToAlign4();
1398                 DUMP_SCALAR(top);
1399                 DUMP_SCALAR(bottom);
1400                 DUMP_SCALAR(constY);
1401                 DUMP_POINT_ARRAY(points);
1402                 } break;
1403             case DRAW_RECT: {
1404                 DUMP_PTR(SkPaint, getPaint());
1405                 DUMP_RECT(rect);
1406                 } break;
1407             case DRAW_SPRITE: {
1408                 DUMP_PTR(SkPaint, getPaint());
1409                 DUMP_PTR(SkBitmap, &getBitmap());
1410                 DUMP_SCALAR(left);
1411                 DUMP_SCALAR(top);
1412                 } break;
1413             case DRAW_TEXT: {
1414                 DUMP_PTR(SkPaint, getPaint());
1415                 DUMP_TEXT();
1416                 DUMP_SCALAR(x);
1417                 DUMP_SCALAR(y);
1418                 } break;
1419             case DRAW_TEXT_ON_PATH: {
1420                 DUMP_PTR(SkPaint, getPaint());
1421                 DUMP_TEXT();
1422                 DUMP_PTR(SkPath, &getPath());
1423                 DUMP_PTR(SkMatrix, getMatrix());
1424                 } break;
1425             case RESTORE:
1426                 break;
1427             case ROTATE:
1428                 DUMP_SCALAR(rotate);
1429                 break;
1430             case SAVE:
1431                 DUMP_INT(SkCanvas::SaveFlags);
1432                 break;
1433             case SAVE_LAYER: {
1434                 DUMP_RECT_PTR(layer);
1435                 DUMP_PTR(SkPaint, getPaint());
1436                 DUMP_INT(SkCanvas::SaveFlags);
1437                 } break;
1438             case SCALE: {
1439                 DUMP_SCALAR(sx);
1440                 DUMP_SCALAR(sy);
1441                 } break;
1442             case SKEW: {
1443                 DUMP_SCALAR(sx);
1444                 DUMP_SCALAR(sy);
1445                 } break;
1446             case TRANSLATE: {
1447                 DUMP_SCALAR(dx);
1448                 DUMP_SCALAR(dy);
1449                 } break;
1450             default:
1451                 SkASSERT(0);
1452         }
1453         SkDebugf("%s\n", buffer);
1454     }
1455 }
1456 
dump() const1457 void SkPicturePlayback::dump() const {
1458     char pBuffer[DUMP_BUFFER_SIZE];
1459     char* bufferPtr = pBuffer;
1460     int index;
1461     if (fBitmapCount > 0)
1462         SkDebugf("// bitmaps (%d)\n", fBitmapCount);
1463     for (index = 0; index < fBitmapCount; index++) {
1464         const SkBitmap& bitmap = fBitmaps[index];
1465         dumpBitmap(bitmap);
1466     }
1467     if (fBitmapCount > 0)
1468         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1469             "Bitmaps bitmaps = {");
1470     for (index = 0; index < fBitmapCount; index++)
1471         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1472             "bitmap%p, ", &fBitmaps[index]);
1473     if (fBitmapCount > 0)
1474         SkDebugf("%s0};\n", pBuffer);
1475 
1476     if (fMatrixCount > 0)
1477         SkDebugf("// matrices (%d)\n", fMatrixCount);
1478     for (index = 0; index < fMatrixCount; index++) {
1479         const SkMatrix& matrix = fMatrices[index];
1480         dumpMatrix(matrix);
1481     }
1482     bufferPtr = pBuffer;
1483     if (fMatrixCount > 0)
1484         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1485             "Matrices matrices = {");
1486     for (index = 0; index < fMatrixCount; index++)
1487         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1488             "matrix%p, ", &fMatrices[index]);
1489     if (fMatrixCount > 0)
1490         SkDebugf("%s0};\n", pBuffer);
1491 
1492     if (fPaintCount > 0)
1493         SkDebugf("// paints (%d)\n", fPaintCount);
1494     for (index = 0; index < fPaintCount; index++) {
1495         const SkPaint& paint = fPaints[index];
1496         dumpPaint(paint);
1497     }
1498     bufferPtr = pBuffer;
1499     if (fPaintCount > 0)
1500         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1501             "Paints paints = {");
1502     for (index = 0; index < fPaintCount; index++)
1503         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1504             "paint%p, ", &fPaints[index]);
1505     if (fPaintCount > 0)
1506         SkDebugf("%s0};\n", pBuffer);
1507 
1508     for (index = 0; index < fPathCount; index++) {
1509         const SkPath& path = fPaths[index];
1510         dumpPath(path);
1511     }
1512     bufferPtr = pBuffer;
1513     if (fPathCount > 0)
1514         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1515             "Paths paths = {");
1516     for (index = 0; index < fPathCount; index++)
1517         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1518             "path%p, ", &fPaths[index]);
1519     if (fPathCount > 0)
1520         SkDebugf("%s0};\n", pBuffer);
1521 
1522     for (index = 0; index < fPictureCount; index++) {
1523         dumpPicture(*fPictureRefs[index]);
1524     }
1525     bufferPtr = pBuffer;
1526     if (fPictureCount > 0)
1527         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1528             "Pictures pictures = {");
1529     for (index = 0; index < fPictureCount; index++)
1530         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1531             "picture%p, ", fPictureRefs[index]);
1532     if (fPictureCount > 0)
1533         SkDebugf("%s0};\n", pBuffer);
1534 
1535     for (index = 0; index < fRegionCount; index++) {
1536         const SkRegion& region = fRegions[index];
1537         dumpRegion(region);
1538     }
1539     bufferPtr = pBuffer;
1540     if (fRegionCount > 0)
1541         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1542             "Regions regions = {");
1543     for (index = 0; index < fRegionCount; index++)
1544         bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1545             "region%p, ", &fRegions[index]);
1546     if (fRegionCount > 0)
1547         SkDebugf("%s0};\n", pBuffer);
1548 
1549     const_cast<SkPicturePlayback*>(this)->dumpStream();
1550 }
1551 
1552 #endif
1553