2 * Copyright 2011 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "SkBBoxHierarchy.h"
9 #include "SkPicturePlayback.h"
10 #include "SkPictureRecord.h"
11 #include "SkPictureStateTree.h"
12 #include "SkReadBuffer.h"
13 #include "SkTypeface.h"
15 #include "SkWriteBuffer.h"
17 template <typename T> int SafeCount(const T* obj) {
18 return obj ? obj->count() : 0;
21 /* Define this to spew out a debug statement whenever we skip the remainder of
22 a save/restore block because a clip... command returned false (empty).
24 #define SPEW_CLIP_SKIPPINGx
26 SkPicturePlayback::SkPicturePlayback(const SkPicture* picture, const SkPictInfo& info)
32 SkPicturePlayback::SkPicturePlayback(const SkPicture* picture,
33 const SkPictureRecord& record,
34 const SkPictInfo& info,
39 size_t overallBytes, bitmapBytes, matricesBytes,
40 paintBytes, pathBytes, pictureBytes, regionBytes;
41 int bitmaps = record.bitmaps(&bitmapBytes);
42 int matrices = record.matrices(&matricesBytes);
43 int paints = record.paints(&paintBytes);
44 int paths = record.paths(&pathBytes);
45 int pictures = record.pictures(&pictureBytes);
46 int regions = record.regions(®ionBytes);
47 SkDebugf("picture record mem used %zd (stream %zd) ", record.size(),
50 SkDebugf("bitmaps size %zd (bitmaps:%d) ", bitmapBytes, bitmaps);
52 SkDebugf("matrices size %zd (matrices:%d) ", matricesBytes, matrices);
54 SkDebugf("paints size %zd (paints:%d) ", paintBytes, paints);
56 SkDebugf("paths size %zd (paths:%d) ", pathBytes, paths);
58 SkDebugf("pictures size %zd (pictures:%d) ", pictureBytes, pictures);
60 SkDebugf("regions size %zd (regions:%d) ", regionBytes, regions);
61 if (record.fPointWrites != 0)
62 SkDebugf("points size %zd (points:%d) ", record.fPointBytes, record.fPointWrites);
63 if (record.fRectWrites != 0)
64 SkDebugf("rects size %zd (rects:%d) ", record.fRectBytes, record.fRectWrites);
65 if (record.fTextWrites != 0)
66 SkDebugf("text size %zd (text strings:%d) ", record.fTextBytes, record.fTextWrites);
71 record.dumpMatrices();
75 record.validate(record.writeStream().bytesWritten(), 0);
76 const SkWriter32& writer = record.writeStream();
79 if (writer.bytesWritten() == 0) {
80 fOpData = SkData::NewEmpty();
83 fOpData = writer.snapshotAsData();
85 fBoundingHierarchy = record.fBoundingHierarchy;
86 fStateTree = record.fStateTree;
88 SkSafeRef(fBoundingHierarchy);
89 SkSafeRef(fStateTree);
91 if (NULL != fBoundingHierarchy) {
92 fBoundingHierarchy->flushDeferredInserts();
95 // copy over the refcnt dictionary to our reader
96 record.fFlattenableHeap.setupPlaybacks();
98 fBitmaps = record.fBitmapHeap->extractBitmaps();
99 fPaints = record.fPaints.unflattenToArray();
101 fBitmapHeap.reset(SkSafeRef(record.fBitmapHeap));
103 picture->initForPlayback();
105 const SkTDArray<SkPicture* >& pictures = record.getPictureRefs();
106 fPictureCount = pictures.count();
107 if (fPictureCount > 0) {
108 fPictureRefs = SkNEW_ARRAY(SkPicture*, fPictureCount);
109 for (int i = 0; i < fPictureCount; i++) {
111 fPictureRefs[i] = pictures[i]->clone();
113 fPictureRefs[i] = pictures[i];
114 fPictureRefs[i]->ref();
120 int overall = fPlayback->size(&overallBytes);
121 bitmaps = fPlayback->bitmaps(&bitmapBytes);
122 paints = fPlayback->paints(&paintBytes);
123 paths = fPlayback->paths(&pathBytes);
124 pictures = fPlayback->pictures(&pictureBytes);
125 regions = fPlayback->regions(®ionBytes);
126 SkDebugf("playback size %zd (objects:%d) ", overallBytes, overall);
128 SkDebugf("bitmaps size %zd (bitmaps:%d) ", bitmapBytes, bitmaps);
130 SkDebugf("paints size %zd (paints:%d) ", paintBytes, paints);
132 SkDebugf("paths size %zd (paths:%d) ", pathBytes, paths);
134 SkDebugf("pictures size %zd (pictures:%d) ", pictureBytes, pictures);
136 SkDebugf("regions size %zd (regions:%d) ", regionBytes, regions);
141 SkPicturePlayback::SkPicturePlayback(const SkPicture* picture, const SkPicturePlayback& src,
142 SkPictCopyInfo* deepCopyInfo)
147 fBitmapHeap.reset(SkSafeRef(src.fBitmapHeap.get()));
149 fOpData = SkSafeRef(src.fOpData);
151 fBoundingHierarchy = src.fBoundingHierarchy;
152 fStateTree = src.fStateTree;
154 SkSafeRef(fBoundingHierarchy);
155 SkSafeRef(fStateTree);
158 SkASSERT(deepCopyInfo->initialized);
160 int paintCount = SafeCount(src.fPaints);
163 fBitmaps = SkTRefArray<SkBitmap>::Create(src.fBitmaps->begin(), src.fBitmaps->count());
166 fPaints = SkTRefArray<SkPaint>::Create(paintCount);
167 SkASSERT(deepCopyInfo->paintData.count() == paintCount);
168 SkBitmapHeap* bmHeap = deepCopyInfo->controller.getBitmapHeap();
169 SkTypefacePlayback* tfPlayback = deepCopyInfo->controller.getTypefacePlayback();
170 for (int i = 0; i < paintCount; i++) {
171 if (deepCopyInfo->paintData[i]) {
172 deepCopyInfo->paintData[i]->unflatten<SkPaint::FlatteningTraits>(
173 &fPaints->writableAt(i), bmHeap, tfPlayback);
175 // needs_deep_copy was false, so just need to assign
176 fPaints->writableAt(i) = src.fPaints->at(i);
181 fBitmaps = SkSafeRef(src.fBitmaps);
182 fPaints = SkSafeRef(src.fPaints);
185 fPictureCount = src.fPictureCount;
186 fPictureRefs = SkNEW_ARRAY(SkPicture*, fPictureCount);
187 for (int i = 0; i < fPictureCount; i++) {
189 fPictureRefs[i] = src.fPictureRefs[i]->clone();
191 fPictureRefs[i] = src.fPictureRefs[i];
192 fPictureRefs[i]->ref();
197 void SkPicturePlayback::init() {
203 fFactoryPlayback = NULL;
204 fBoundingHierarchy = NULL;
206 fCachedActiveOps = NULL;
210 SkPicturePlayback::~SkPicturePlayback() {
211 SkSafeUnref(fOpData);
213 SkSafeUnref(fBitmaps);
214 SkSafeUnref(fPaints);
215 SkSafeUnref(fBoundingHierarchy);
216 SkSafeUnref(fStateTree);
218 SkDELETE(fCachedActiveOps);
220 for (int i = 0; i < fPictureCount; i++) {
221 fPictureRefs[i]->unref();
223 SkDELETE_ARRAY(fPictureRefs);
225 SkDELETE(fFactoryPlayback);
228 void SkPicturePlayback::dumpSize() const {
229 SkDebugf("--- picture size: ops=%d bitmaps=%d [%d] paints=%d [%d]\n",
231 SafeCount(fBitmaps), SafeCount(fBitmaps) * sizeof(SkBitmap),
232 SafeCount(fPaints), SafeCount(fPaints) * sizeof(SkPaint));
233 fPicture->dumpSize();
236 bool SkPicturePlayback::containsBitmaps() const {
237 if (fBitmaps && fBitmaps->count() > 0) {
240 for (int i = 0; i < fPictureCount; ++i) {
241 if (fPictureRefs[i]->willPlayBackBitmaps()) {
248 ///////////////////////////////////////////////////////////////////////////////
249 ///////////////////////////////////////////////////////////////////////////////
251 #include "SkStream.h"
253 static size_t compute_chunk_size(SkFlattenable::Factory* array, int count) {
254 size_t size = 4; // for 'count'
256 for (int i = 0; i < count; i++) {
257 const char* name = SkFlattenable::FactoryToName(array[i]);
258 if (NULL == name || 0 == *name) {
259 size += SkWStream::SizeOfPackedUInt(0);
261 size_t len = strlen(name);
262 size += SkWStream::SizeOfPackedUInt(len);
270 void SkPicturePlayback::WriteFactories(SkWStream* stream, const SkFactorySet& rec) {
271 int count = rec.count();
273 SkAutoSTMalloc<16, SkFlattenable::Factory> storage(count);
274 SkFlattenable::Factory* array = (SkFlattenable::Factory*)storage.get();
275 rec.copyToArray(array);
277 size_t size = compute_chunk_size(array, count);
279 // TODO: write_tag_size should really take a size_t
280 SkPicture::WriteTagSize(stream, SK_PICT_FACTORY_TAG, (uint32_t) size);
281 SkDEBUGCODE(size_t start = stream->bytesWritten());
282 stream->write32(count);
284 for (int i = 0; i < count; i++) {
285 const char* name = SkFlattenable::FactoryToName(array[i]);
286 // SkDebugf("---- write factories [%d] %p <%s>\n", i, array[i], name);
287 if (NULL == name || 0 == *name) {
288 stream->writePackedUInt(0);
290 size_t len = strlen(name);
291 stream->writePackedUInt(len);
292 stream->write(name, len);
296 SkASSERT(size == (stream->bytesWritten() - start));
299 void SkPicturePlayback::WriteTypefaces(SkWStream* stream, const SkRefCntSet& rec) {
300 int count = rec.count();
302 SkPicture::WriteTagSize(stream, SK_PICT_TYPEFACE_TAG, count);
304 SkAutoSTMalloc<16, SkTypeface*> storage(count);
305 SkTypeface** array = (SkTypeface**)storage.get();
306 rec.copyToArray((SkRefCnt**)array);
308 for (int i = 0; i < count; i++) {
309 array[i]->serialize(stream);
313 void SkPicturePlayback::flattenToBuffer(SkWriteBuffer& buffer) const {
316 if ((n = SafeCount(fBitmaps)) > 0) {
317 SkPicture::WriteTagSize(buffer, SK_PICT_BITMAP_BUFFER_TAG, n);
318 for (i = 0; i < n; i++) {
319 buffer.writeBitmap((*fBitmaps)[i]);
323 if ((n = SafeCount(fPaints)) > 0) {
324 SkPicture::WriteTagSize(buffer, SK_PICT_PAINT_BUFFER_TAG, n);
325 for (i = 0; i < n; i++) {
326 buffer.writePaint((*fPaints)[i]);
330 fPicture->flattenToBuffer(buffer);
333 void SkPicturePlayback::serialize(SkWStream* stream,
334 SkPicture::EncodeBitmap encoder) const {
335 SkPicture::WriteTagSize(stream, SK_PICT_READER_TAG, fOpData->size());
336 stream->write(fOpData->bytes(), fOpData->size());
338 if (fPictureCount > 0) {
339 SkPicture::WriteTagSize(stream, SK_PICT_PICTURE_TAG, fPictureCount);
340 for (int i = 0; i < fPictureCount; i++) {
341 fPictureRefs[i]->serialize(stream, encoder);
345 // Write some of our data into a writebuffer, and then serialize that
348 SkRefCntSet typefaceSet;
349 SkFactorySet factSet;
351 SkWriteBuffer buffer(SkWriteBuffer::kCrossProcess_Flag);
352 buffer.setTypefaceRecorder(&typefaceSet);
353 buffer.setFactoryRecorder(&factSet);
354 buffer.setBitmapEncoder(encoder);
356 this->flattenToBuffer(buffer);
358 // We have to write these two sets into the stream *before* we write
359 // the buffer, since parsing that buffer will require that we already
360 // have these sets available to use.
361 WriteFactories(stream, factSet);
362 WriteTypefaces(stream, typefaceSet);
364 SkPicture::WriteTagSize(stream, SK_PICT_BUFFER_SIZE_TAG, buffer.bytesWritten());
365 buffer.writeToStream(stream);
368 stream->write32(SK_PICT_EOF_TAG);
371 void SkPicturePlayback::flatten(SkWriteBuffer& buffer) const {
372 SkPicture::WriteTagSize(buffer, SK_PICT_READER_TAG, fOpData->size());
373 buffer.writeByteArray(fOpData->bytes(), fOpData->size());
375 if (fPictureCount > 0) {
376 SkPicture::WriteTagSize(buffer, SK_PICT_PICTURE_TAG, fPictureCount);
377 for (int i = 0; i < fPictureCount; i++) {
378 fPictureRefs[i]->flatten(buffer);
382 // Write this picture playback's data into a writebuffer
383 this->flattenToBuffer(buffer);
384 buffer.write32(SK_PICT_EOF_TAG);
387 ///////////////////////////////////////////////////////////////////////////////
390 * Return the corresponding SkReadBuffer flags, given a set of
393 static uint32_t pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags) {
394 static const struct {
398 { SkPictInfo::kCrossProcess_Flag, SkReadBuffer::kCrossProcess_Flag },
399 { SkPictInfo::kScalarIsFloat_Flag, SkReadBuffer::kScalarIsFloat_Flag },
400 { SkPictInfo::kPtrIs64Bit_Flag, SkReadBuffer::kPtrIs64Bit_Flag },
404 for (size_t i = 0; i < SK_ARRAY_COUNT(gSD); ++i) {
405 if (pictInfoFlags & gSD[i].fSrc) {
406 rbMask |= gSD[i].fDst;
412 bool SkPicturePlayback::parseStreamTag(SkPicture* picture,
416 SkPicture::InstallPixelRefProc proc) {
418 * By the time we encounter BUFFER_SIZE_TAG, we need to have already seen
419 * its dependents: FACTORY_TAG and TYPEFACE_TAG. These two are not required
420 * but if they are present, they need to have been seen before the buffer.
422 * We assert that if/when we see either of these, that we have not yet seen
423 * the buffer tag, because if we have, then its too-late to deal with the
424 * factories or typefaces.
426 SkDEBUGCODE(bool haveBuffer = false;)
429 case SK_PICT_READER_TAG: {
430 SkAutoMalloc storage(size);
431 if (stream->read(storage.get(), size) != size) {
434 SkASSERT(NULL == fOpData);
435 fOpData = SkData::NewFromMalloc(storage.detach(), size);
437 case SK_PICT_FACTORY_TAG: {
438 SkASSERT(!haveBuffer);
439 // Remove this code when v21 and below are no longer supported. At the
440 // same time add a new 'count' variable and use it rather then reusing 'size'.
441 #ifndef DISABLE_V21_COMPATIBILITY_CODE
442 if (fInfo.fVersion >= 22) {
443 // in v22 this tag's size represents the size of the chunk in bytes
444 // and the number of factory strings is written out separately
446 size = stream->readU32();
447 #ifndef DISABLE_V21_COMPATIBILITY_CODE
450 fFactoryPlayback = SkNEW_ARGS(SkFactoryPlayback, (size));
451 for (size_t i = 0; i < size; i++) {
453 const size_t len = stream->readPackedUInt();
455 if (stream->read(str.writable_str(), len) != len) {
458 fFactoryPlayback->base()[i] = SkFlattenable::NameToFactory(str.c_str());
461 case SK_PICT_TYPEFACE_TAG: {
462 SkASSERT(!haveBuffer);
463 const int count = SkToInt(size);
464 fTFPlayback.setCount(count);
465 for (int i = 0; i < count; i++) {
466 SkAutoTUnref<SkTypeface> tf(SkTypeface::Deserialize(stream));
467 if (!tf.get()) { // failed to deserialize
468 // fTFPlayback asserts it never has a null, so we plop in
470 tf.reset(SkTypeface::RefDefault());
472 fTFPlayback.set(i, tf);
475 case SK_PICT_PICTURE_TAG: {
476 fPictureCount = size;
477 fPictureRefs = SkNEW_ARRAY(SkPicture*, fPictureCount);
480 for ( ; i < fPictureCount; i++) {
481 fPictureRefs[i] = SkPicture::CreateFromStream(stream, proc);
482 if (NULL == fPictureRefs[i]) {
488 // Delete all of the pictures that were already created (up to but excluding i):
489 for (int j = 0; j < i; j++) {
490 fPictureRefs[j]->unref();
493 SkDELETE_ARRAY(fPictureRefs);
498 case SK_PICT_BUFFER_SIZE_TAG: {
499 SkAutoMalloc storage(size);
500 if (stream->read(storage.get(), size) != size) {
504 SkReadBuffer buffer(storage.get(), size);
505 buffer.setFlags(pictInfoFlagsToReadBufferFlags(fInfo.fFlags));
506 buffer.setPictureVersion(fInfo.fVersion);
508 fFactoryPlayback->setupBuffer(buffer);
509 fTFPlayback.setupBuffer(buffer);
510 buffer.setBitmapDecoder(proc);
512 while (!buffer.eof()) {
513 tag = buffer.readUInt();
514 size = buffer.readUInt();
515 if (!this->parseBufferTag(picture, buffer, tag, size)) {
519 SkDEBUGCODE(haveBuffer = true;)
522 return true; // success
525 bool SkPicturePlayback::parseBufferTag(SkPicture* picture,
526 SkReadBuffer& buffer,
527 uint32_t tag, uint32_t size) {
529 case SK_PICT_BITMAP_BUFFER_TAG: {
530 const int count = SkToInt(size);
531 fBitmaps = SkTRefArray<SkBitmap>::Create(size);
532 for (int i = 0; i < count; ++i) {
533 SkBitmap* bm = &fBitmaps->writableAt(i);
534 buffer.readBitmap(bm);
538 case SK_PICT_PAINT_BUFFER_TAG: {
539 const int count = SkToInt(size);
540 fPaints = SkTRefArray<SkPaint>::Create(size);
541 for (int i = 0; i < count; ++i) {
542 buffer.readPaint(&fPaints->writableAt(i));
545 case SK_PICT_PATH_BUFFER_TAG:
546 picture->parseBufferTag(buffer, tag, size);
548 case SK_PICT_READER_TAG: {
549 SkAutoMalloc storage(size);
550 if (!buffer.readByteArray(storage.get(), size) ||
551 !buffer.validate(NULL == fOpData)) {
554 SkASSERT(NULL == fOpData);
555 fOpData = SkData::NewFromMalloc(storage.detach(), size);
557 case SK_PICT_PICTURE_TAG: {
558 if (!buffer.validate((0 == fPictureCount) && (NULL == fPictureRefs))) {
561 fPictureCount = size;
562 fPictureRefs = SkNEW_ARRAY(SkPicture*, fPictureCount);
565 for ( ; i < fPictureCount; i++) {
566 fPictureRefs[i] = SkPicture::CreateFromBuffer(buffer);
567 if (NULL == fPictureRefs[i]) {
573 // Delete all of the pictures that were already created (up to but excluding i):
574 for (int j = 0; j < i; j++) {
575 fPictureRefs[j]->unref();
578 SkDELETE_ARRAY(fPictureRefs);
584 // The tag was invalid.
587 return true; // success
590 SkPicturePlayback* SkPicturePlayback::CreateFromStream(SkPicture* picture,
592 const SkPictInfo& info,
593 SkPicture::InstallPixelRefProc proc) {
594 SkAutoTDelete<SkPicturePlayback> playback(SkNEW_ARGS(SkPicturePlayback, (picture, info)));
596 if (!playback->parseStream(picture, stream, proc)) {
599 return playback.detach();
602 SkPicturePlayback* SkPicturePlayback::CreateFromBuffer(SkPicture* picture,
603 SkReadBuffer& buffer,
604 const SkPictInfo& info) {
605 SkAutoTDelete<SkPicturePlayback> playback(SkNEW_ARGS(SkPicturePlayback, (picture, info)));
606 buffer.setPictureVersion(info.fVersion);
608 if (!playback->parseBuffer(picture, buffer)) {
611 return playback.detach();
614 bool SkPicturePlayback::parseStream(SkPicture* picture,
616 SkPicture::InstallPixelRefProc proc) {
618 uint32_t tag = stream->readU32();
619 if (SK_PICT_EOF_TAG == tag) {
623 uint32_t size = stream->readU32();
624 if (!this->parseStreamTag(picture, stream, tag, size, proc)) {
625 return false; // we're invalid
631 bool SkPicturePlayback::parseBuffer(SkPicture* picture, SkReadBuffer& buffer) {
633 uint32_t tag = buffer.readUInt();
634 if (SK_PICT_EOF_TAG == tag) {
638 uint32_t size = buffer.readUInt();
639 if (!this->parseBufferTag(picture, buffer, tag, size)) {
640 return false; // we're invalid
646 ///////////////////////////////////////////////////////////////////////////////
647 ///////////////////////////////////////////////////////////////////////////////
649 #ifdef SPEW_CLIP_SKIPPING
659 void recordSkip(size_t bytes) {
667 bool SkPicturePlayback::preDraw(int opIndex, int type) {
671 void SkPicturePlayback::postDraw(int opIndex) {
676 * Read the next op code and chunk size from 'reader'. The returned size
677 * is the entire size of the chunk (including the opcode). Thus, the
678 * offset just prior to calling read_op_and_size + 'size' is the offset
679 * to the next chunk's op code. This also means that the size of a chunk
680 * with no arguments (just an opcode) will be 4.
682 static DrawType read_op_and_size(SkReader32* reader, uint32_t* size) {
683 uint32_t temp = reader->readInt();
685 if (((uint8_t) temp) == temp) {
686 // old skp file - no size information
690 UNPACK_8_24(temp, op, *size);
691 if (MASK_24 == *size) {
692 *size = reader->readInt();
695 return (DrawType) op;
698 uint32_t SkPicturePlayback::CachedOperationList::offset(int index) const {
699 SkASSERT(index < fOps.count());
700 return ((SkPictureStateTree::Draw*)fOps[index])->fOffset;
703 const SkMatrix& SkPicturePlayback::CachedOperationList::matrix(int index) const {
704 SkASSERT(index < fOps.count());
705 return *((SkPictureStateTree::Draw*)fOps[index])->fMatrix;
708 const SkPicture::OperationList& SkPicturePlayback::getActiveOps(const SkIRect& query) {
709 if (NULL == fStateTree || NULL == fBoundingHierarchy) {
710 return SkPicture::OperationList::InvalidList();
713 if (NULL == fCachedActiveOps) {
714 fCachedActiveOps = SkNEW(CachedOperationList);
717 if (query == fCachedActiveOps->fCacheQueryRect) {
718 return *fCachedActiveOps;
721 fCachedActiveOps->fOps.rewind();
723 fBoundingHierarchy->search(query, &(fCachedActiveOps->fOps));
724 if (0 != fCachedActiveOps->fOps.count()) {
725 SkTQSort<SkPictureStateTree::Draw>(
726 reinterpret_cast<SkPictureStateTree::Draw**>(fCachedActiveOps->fOps.begin()),
727 reinterpret_cast<SkPictureStateTree::Draw**>(fCachedActiveOps->fOps.end()-1));
730 fCachedActiveOps->fCacheQueryRect = query;
731 return *fCachedActiveOps;
734 class SkAutoResetOpID {
736 SkAutoResetOpID(SkPicturePlayback* playback) : fPlayback(playback) { }
738 if (NULL != fPlayback) {
739 fPlayback->resetOpID();
744 SkPicturePlayback* fPlayback;
747 void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback) {
748 SkAutoResetOpID aroi(this);
749 SkASSERT(0 == fCurOffset);
751 #ifdef ENABLE_TIME_DRAW
752 SkAutoTime at("SkPicture::draw", 50);
755 #ifdef SPEW_CLIP_SKIPPING
756 SkipClipRec skipRect, skipRRect, skipRegion, skipPath, skipCull;
760 #ifdef SK_BUILD_FOR_ANDROID
761 SkAutoMutexAcquire autoMutex(fDrawMutex);
764 // kDrawComplete will be the signal that we have reached the end of
765 // the command stream
766 static const uint32_t kDrawComplete = SK_MaxU32;
768 SkReader32 reader(fOpData->bytes(), fOpData->size());
770 const SkTDArray<void*>* activeOps = NULL;
772 if (NULL != fStateTree && NULL != fBoundingHierarchy) {
774 if (canvas.getClipBounds(&clipBounds)) {
776 clipBounds.roundOut(&query);
778 const SkPicture::OperationList& activeOpsList = this->getActiveOps(query);
779 if (activeOpsList.valid()) {
780 if (0 == activeOpsList.numOps()) {
781 return; // nothing to draw
784 // Since the opList is valid we know it is our derived class
785 activeOps = &((const CachedOperationList&)activeOpsList).fOps;
790 SkPictureStateTree::Iterator it = (NULL == activeOps) ?
791 SkPictureStateTree::Iterator() :
792 fStateTree->getIterator(*activeOps, &canvas);
795 uint32_t skipTo = it.nextDraw();
796 if (kDrawComplete == skipTo) {
799 reader.setOffset(skipTo);
802 // Record this, so we can concat w/ it if we encounter a setMatrix()
803 SkMatrix initialMatrix = canvas.getTotalMatrix();
804 int originalSaveCount = canvas.getSaveCount();
806 #ifdef SK_BUILD_FOR_ANDROID
807 fAbortCurrentPlayback = false;
814 while (!reader.eof()) {
815 if (callback && callback->abortDrawing()) {
816 canvas.restoreToCount(originalSaveCount);
819 #ifdef SK_BUILD_FOR_ANDROID
820 if (fAbortCurrentPlayback) {
825 #ifdef SPEW_CLIP_SKIPPING
829 fCurOffset = reader.offset();
831 DrawType op = read_op_and_size(&reader, &size);
834 // NOOPs are to be ignored - do not propagate them any further
835 skipTo = fCurOffset + size;
839 if (this->preDraw(opIndex, op)) {
840 skipTo = fCurOffset + size;
847 // If using a bounding box hierarchy, advance the state tree
848 // iterator until at or after skipTo
849 uint32_t adjustedSkipTo;
851 adjustedSkipTo = it.nextDraw();
852 } while (adjustedSkipTo < skipTo);
853 skipTo = adjustedSkipTo;
855 if (kDrawComplete == skipTo) {
858 reader.setOffset(skipTo);
864 const SkPath& path = getPath(reader);
865 uint32_t packed = reader.readInt();
866 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
867 bool doAA = ClipParams_unpackDoAA(packed);
868 size_t offsetToRestore = reader.readInt();
869 SkASSERT(!offsetToRestore || \
870 offsetToRestore >= reader.offset());
871 canvas.clipPath(path, regionOp, doAA);
872 if (canvas.isClipEmpty() && offsetToRestore) {
873 #ifdef SPEW_CLIP_SKIPPING
874 skipPath.recordSkip(offsetToRestore - reader.offset());
876 reader.setOffset(offsetToRestore);
881 this->getRegion(reader, ®ion);
882 uint32_t packed = reader.readInt();
883 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
884 size_t offsetToRestore = reader.readInt();
885 SkASSERT(!offsetToRestore || \
886 offsetToRestore >= reader.offset());
887 canvas.clipRegion(region, regionOp);
888 if (canvas.isClipEmpty() && offsetToRestore) {
889 #ifdef SPEW_CLIP_SKIPPING
890 skipRegion.recordSkip(offsetToRestore - reader.offset());
892 reader.setOffset(offsetToRestore);
896 const SkRect& rect = reader.skipT<SkRect>();
897 uint32_t packed = reader.readInt();
898 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
899 bool doAA = ClipParams_unpackDoAA(packed);
900 size_t offsetToRestore = reader.readInt();
901 SkASSERT(!offsetToRestore || \
902 offsetToRestore >= reader.offset());
903 canvas.clipRect(rect, regionOp, doAA);
904 if (canvas.isClipEmpty() && offsetToRestore) {
905 #ifdef SPEW_CLIP_SKIPPING
906 skipRect.recordSkip(offsetToRestore - reader.offset());
908 reader.setOffset(offsetToRestore);
913 reader.readRRect(&rrect);
914 uint32_t packed = reader.readInt();
915 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
916 bool doAA = ClipParams_unpackDoAA(packed);
917 size_t offsetToRestore = reader.readInt();
918 SkASSERT(!offsetToRestore || \
919 offsetToRestore >= reader.offset());
920 canvas.clipRRect(rrect, regionOp, doAA);
921 if (canvas.isClipEmpty() && offsetToRestore) {
922 #ifdef SPEW_CLIP_SKIPPING
923 skipRRect.recordSkip(offsetToRestore - reader.offset());
925 reader.setOffset(offsetToRestore);
929 const SkRect& cullRect = reader.skipT<SkRect>();
930 size_t offsetToRestore = reader.readInt();
931 if (offsetToRestore && canvas.quickReject(cullRect)) {
932 #ifdef SPEW_CLIP_SKIPPING
933 skipCull.recordSkip(offsetToRestore - reader.offset());
935 reader.setOffset(offsetToRestore);
937 canvas.pushCull(cullRect);
945 this->getMatrix(reader, &matrix);
946 canvas.concat(matrix);
950 const SkPaint* paint = this->getPaint(reader);
951 const SkBitmap& bitmap = this->getBitmap(reader);
952 const SkPoint& loc = reader.skipT<SkPoint>();
953 canvas.drawBitmap(bitmap, loc.fX, loc.fY, paint);
955 case DRAW_BITMAP_RECT_TO_RECT: {
956 const SkPaint* paint = this->getPaint(reader);
957 const SkBitmap& bitmap = this->getBitmap(reader);
958 const SkRect* src = this->getRectPtr(reader); // may be null
959 const SkRect& dst = reader.skipT<SkRect>(); // required
960 SkCanvas::DrawBitmapRectFlags flags;
961 flags = (SkCanvas::DrawBitmapRectFlags) reader.readInt();
962 canvas.drawBitmapRectToRect(bitmap, src, dst, paint, flags);
964 case DRAW_BITMAP_MATRIX: {
965 const SkPaint* paint = this->getPaint(reader);
966 const SkBitmap& bitmap = this->getBitmap(reader);
968 this->getMatrix(reader, &matrix);
969 canvas.drawBitmapMatrix(bitmap, matrix, paint);
971 case DRAW_BITMAP_NINE: {
972 const SkPaint* paint = this->getPaint(reader);
973 const SkBitmap& bitmap = this->getBitmap(reader);
974 const SkIRect& src = reader.skipT<SkIRect>();
975 const SkRect& dst = reader.skipT<SkRect>();
976 canvas.drawBitmapNine(bitmap, src, dst, paint);
979 canvas.clear(reader.readInt());
982 size_t length = reader.readInt();
983 canvas.drawData(reader.skip(length), length);
984 // skip handles padding the read out to a multiple of 4
987 const SkPaint& paint = *this->getPaint(reader);
988 SkRRect outer, inner;
989 reader.readRRect(&outer);
990 reader.readRRect(&inner);
991 canvas.drawDRRect(outer, inner, paint);
993 case BEGIN_COMMENT_GROUP: {
994 const char* desc = reader.readString();
995 canvas.beginCommentGroup(desc);
998 const char* kywd = reader.readString();
999 const char* value = reader.readString();
1000 canvas.addComment(kywd, value);
1002 case END_COMMENT_GROUP: {
1003 canvas.endCommentGroup();
1006 const SkPaint& paint = *this->getPaint(reader);
1007 canvas.drawOval(reader.skipT<SkRect>(), paint);
1010 canvas.drawPaint(*this->getPaint(reader));
1013 const SkPaint& paint = *this->getPaint(reader);
1014 canvas.drawPath(getPath(reader), paint);
1017 canvas.drawPicture(this->getPicture(reader));
1020 const SkPaint& paint = *this->getPaint(reader);
1021 SkCanvas::PointMode mode = (SkCanvas::PointMode)reader.readInt();
1022 size_t count = reader.readInt();
1023 const SkPoint* pts = (const SkPoint*)reader.skip(sizeof(SkPoint) * count);
1024 canvas.drawPoints(mode, count, pts, paint);
1026 case DRAW_POS_TEXT: {
1027 const SkPaint& paint = *this->getPaint(reader);
1028 getText(reader, &text);
1029 size_t points = reader.readInt();
1030 const SkPoint* pos = (const SkPoint*)reader.skip(points * sizeof(SkPoint));
1031 canvas.drawPosText(text.text(), text.length(), pos, paint);
1033 case DRAW_POS_TEXT_TOP_BOTTOM: {
1034 const SkPaint& paint = *this->getPaint(reader);
1035 getText(reader, &text);
1036 size_t points = reader.readInt();
1037 const SkPoint* pos = (const SkPoint*)reader.skip(points * sizeof(SkPoint));
1038 const SkScalar top = reader.readScalar();
1039 const SkScalar bottom = reader.readScalar();
1040 if (!canvas.quickRejectY(top, bottom)) {
1041 canvas.drawPosText(text.text(), text.length(), pos, paint);
1044 case DRAW_POS_TEXT_H: {
1045 const SkPaint& paint = *this->getPaint(reader);
1046 getText(reader, &text);
1047 size_t xCount = reader.readInt();
1048 const SkScalar constY = reader.readScalar();
1049 const SkScalar* xpos = (const SkScalar*)reader.skip(xCount * sizeof(SkScalar));
1050 canvas.drawPosTextH(text.text(), text.length(), xpos, constY,
1053 case DRAW_POS_TEXT_H_TOP_BOTTOM: {
1054 const SkPaint& paint = *this->getPaint(reader);
1055 getText(reader, &text);
1056 size_t xCount = reader.readInt();
1057 const SkScalar* xpos = (const SkScalar*)reader.skip((3 + xCount) * sizeof(SkScalar));
1058 const SkScalar top = *xpos++;
1059 const SkScalar bottom = *xpos++;
1060 const SkScalar constY = *xpos++;
1061 if (!canvas.quickRejectY(top, bottom)) {
1062 canvas.drawPosTextH(text.text(), text.length(), xpos,
1067 const SkPaint& paint = *this->getPaint(reader);
1068 canvas.drawRect(reader.skipT<SkRect>(), paint);
1071 const SkPaint& paint = *this->getPaint(reader);
1073 reader.readRRect(&rrect);
1074 canvas.drawRRect(rrect, paint);
1077 const SkPaint* paint = this->getPaint(reader);
1078 const SkBitmap& bitmap = this->getBitmap(reader);
1079 int left = reader.readInt();
1080 int top = reader.readInt();
1081 canvas.drawSprite(bitmap, left, top, paint);
1084 const SkPaint& paint = *this->getPaint(reader);
1085 this->getText(reader, &text);
1086 SkScalar x = reader.readScalar();
1087 SkScalar y = reader.readScalar();
1088 canvas.drawText(text.text(), text.length(), x, y, paint);
1090 case DRAW_TEXT_TOP_BOTTOM: {
1091 const SkPaint& paint = *this->getPaint(reader);
1092 this->getText(reader, &text);
1093 const SkScalar* ptr = (const SkScalar*)reader.skip(4 * sizeof(SkScalar));
1098 if (!canvas.quickRejectY(ptr[2], ptr[3])) {
1099 canvas.drawText(text.text(), text.length(), ptr[0], ptr[1],
1103 case DRAW_TEXT_ON_PATH: {
1104 const SkPaint& paint = *this->getPaint(reader);
1105 getText(reader, &text);
1106 const SkPath& path = this->getPath(reader);
1108 this->getMatrix(reader, &matrix);
1109 canvas.drawTextOnPath(text.text(), text.length(), path, &matrix, paint);
1111 case DRAW_VERTICES: {
1112 SkAutoTUnref<SkXfermode> xfer;
1113 const SkPaint& paint = *this->getPaint(reader);
1114 DrawVertexFlags flags = (DrawVertexFlags)reader.readInt();
1115 SkCanvas::VertexMode vmode = (SkCanvas::VertexMode)reader.readInt();
1116 int vCount = reader.readInt();
1117 const SkPoint* verts = (const SkPoint*)reader.skip(
1118 vCount * sizeof(SkPoint));
1119 const SkPoint* texs = NULL;
1120 const SkColor* colors = NULL;
1121 const uint16_t* indices = NULL;
1123 if (flags & DRAW_VERTICES_HAS_TEXS) {
1124 texs = (const SkPoint*)reader.skip(
1125 vCount * sizeof(SkPoint));
1127 if (flags & DRAW_VERTICES_HAS_COLORS) {
1128 colors = (const SkColor*)reader.skip(
1129 vCount * sizeof(SkColor));
1131 if (flags & DRAW_VERTICES_HAS_INDICES) {
1132 iCount = reader.readInt();
1133 indices = (const uint16_t*)reader.skip(
1134 iCount * sizeof(uint16_t));
1136 if (flags & DRAW_VERTICES_HAS_XFER) {
1137 int mode = reader.readInt();
1138 if (mode < 0 || mode > SkXfermode::kLastMode) {
1139 mode = SkXfermode::kModulate_Mode;
1141 xfer.reset(SkXfermode::Create((SkXfermode::Mode)mode));
1143 canvas.drawVertices(vmode, vCount, verts, texs, colors, xfer,
1144 indices, iCount, paint);
1150 canvas.rotate(reader.readScalar());
1153 canvas.save((SkCanvas::SaveFlags) reader.readInt());
1156 const SkRect* boundsPtr = this->getRectPtr(reader);
1157 const SkPaint* paint = this->getPaint(reader);
1158 canvas.saveLayer(boundsPtr, paint, (SkCanvas::SaveFlags) reader.readInt());
1161 SkScalar sx = reader.readScalar();
1162 SkScalar sy = reader.readScalar();
1163 canvas.scale(sx, sy);
1167 this->getMatrix(reader, &matrix);
1168 matrix.postConcat(initialMatrix);
1169 canvas.setMatrix(matrix);
1172 SkScalar sx = reader.readScalar();
1173 SkScalar sy = reader.readScalar();
1174 canvas.skew(sx, sy);
1177 SkScalar dx = reader.readScalar();
1178 SkScalar dy = reader.readScalar();
1179 canvas.translate(dx, dy);
1186 this->postDraw(opIndex);
1190 uint32_t skipTo = it.nextDraw();
1191 if (kDrawComplete == skipTo) {
1194 reader.setOffset(skipTo);
1198 #ifdef SPEW_CLIP_SKIPPING
1200 size_t size = skipRect.fSize + skipRRect.fSize + skipPath.fSize + skipRegion.fSize +
1202 SkDebugf("--- Clip skips %d%% rect:%d rrect:%d path:%d rgn:%d cull:%d\n",
1203 size * 100 / reader.offset(), skipRect.fCount, skipRRect.fCount,
1204 skipPath.fCount, skipRegion.fCount, skipCull.fCount);
1205 SkDebugf("--- Total ops: %d\n", opCount);
1208 // this->dumpSize();
1211 ///////////////////////////////////////////////////////////////////////////////
1213 #ifdef SK_DEBUG_SIZE
1214 int SkPicturePlayback::size(size_t* sizePtr) {
1215 int objects = bitmaps(sizePtr);
1216 objects += paints(sizePtr);
1217 objects += paths(sizePtr);
1218 objects += pictures(sizePtr);
1219 objects += regions(sizePtr);
1220 *sizePtr = fOpData.size();
1224 int SkPicturePlayback::bitmaps(size_t* size) {
1226 for (int index = 0; index < fBitmapCount; index++) {
1227 // const SkBitmap& bitmap = fBitmaps[index];
1228 result += sizeof(SkBitmap); // bitmap->size();
1231 return fBitmapCount;
1234 int SkPicturePlayback::paints(size_t* size) {
1236 for (int index = 0; index < fPaintCount; index++) {
1237 // const SkPaint& paint = fPaints[index];
1238 result += sizeof(SkPaint); // paint->size();
1244 int SkPicturePlayback::paths(size_t* size) {
1246 for (int index = 0; index < fPathCount; index++) {
1247 const SkPath& path = fPaths[index];
1248 result += path.flatten(NULL);
1255 #ifdef SK_DEBUG_DUMP
1256 void SkPicturePlayback::dumpBitmap(const SkBitmap& bitmap) const {
1257 char pBuffer[DUMP_BUFFER_SIZE];
1258 char* bufferPtr = pBuffer;
1259 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1260 "BitmapData bitmap%p = {", &bitmap);
1261 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1262 "{kWidth, %d}, ", bitmap.width());
1263 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1264 "{kHeight, %d}, ", bitmap.height());
1265 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1266 "{kRowBytes, %d}, ", bitmap.rowBytes());
1268 SkDebugf("%s{0}};\n", pBuffer);
1271 void dumpMatrix(const SkMatrix& matrix) const {
1272 SkMatrix defaultMatrix;
1273 defaultMatrix.reset();
1274 char pBuffer[DUMP_BUFFER_SIZE];
1275 char* bufferPtr = pBuffer;
1276 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1277 "MatrixData matrix%p = {", &matrix);
1278 SkScalar scaleX = matrix.getScaleX();
1279 if (scaleX != defaultMatrix.getScaleX())
1280 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1281 "{kScaleX, %g}, ", SkScalarToFloat(scaleX));
1282 SkScalar scaleY = matrix.getScaleY();
1283 if (scaleY != defaultMatrix.getScaleY())
1284 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1285 "{kScaleY, %g}, ", SkScalarToFloat(scaleY));
1286 SkScalar skewX = matrix.getSkewX();
1287 if (skewX != defaultMatrix.getSkewX())
1288 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1289 "{kSkewX, %g}, ", SkScalarToFloat(skewX));
1290 SkScalar skewY = matrix.getSkewY();
1291 if (skewY != defaultMatrix.getSkewY())
1292 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1293 "{kSkewY, %g}, ", SkScalarToFloat(skewY));
1294 SkScalar translateX = matrix.getTranslateX();
1295 if (translateX != defaultMatrix.getTranslateX())
1296 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1297 "{kTranslateX, %g}, ", SkScalarToFloat(translateX));
1298 SkScalar translateY = matrix.getTranslateY();
1299 if (translateY != defaultMatrix.getTranslateY())
1300 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1301 "{kTranslateY, %g}, ", SkScalarToFloat(translateY));
1302 SkScalar perspX = matrix.getPerspX();
1303 if (perspX != defaultMatrix.getPerspX())
1304 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1305 "{kPerspX, %g}, ", perspX);
1306 SkScalar perspY = matrix.getPerspY();
1307 if (perspY != defaultMatrix.getPerspY())
1308 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1309 "{kPerspY, %g}, ", perspY);
1310 SkDebugf("%s{0}};\n", pBuffer);
1313 void dumpPaint(const SkPaint& paint) const {
1314 SkPaint defaultPaint;
1315 char pBuffer[DUMP_BUFFER_SIZE];
1316 char* bufferPtr = pBuffer;
1317 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1318 "PaintPointers paintPtrs%p = {", &paint);
1319 const SkTypeface* typeface = paint.getTypeface();
1320 if (typeface != defaultPaint.getTypeface())
1321 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1322 "{kTypeface, %p}, ", typeface);
1323 const SkPathEffect* pathEffect = paint.getPathEffect();
1324 if (pathEffect != defaultPaint.getPathEffect())
1325 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1326 "{kPathEffect, %p}, ", pathEffect);
1327 const SkShader* shader = paint.getShader();
1328 if (shader != defaultPaint.getShader())
1329 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1330 "{kShader, %p}, ", shader);
1331 const SkXfermode* xfermode = paint.getXfermode();
1332 if (xfermode != defaultPaint.getXfermode())
1333 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1334 "{kXfermode, %p}, ", xfermode);
1335 const SkMaskFilter* maskFilter = paint.getMaskFilter();
1336 if (maskFilter != defaultPaint.getMaskFilter())
1337 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1338 "{kMaskFilter, %p}, ", maskFilter);
1339 const SkColorFilter* colorFilter = paint.getColorFilter();
1340 if (colorFilter != defaultPaint.getColorFilter())
1341 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1342 "{kColorFilter, %p}, ", colorFilter);
1343 const SkRasterizer* rasterizer = paint.getRasterizer();
1344 if (rasterizer != defaultPaint.getRasterizer())
1345 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1346 "{kRasterizer, %p}, ", rasterizer);
1347 const SkDrawLooper* drawLooper = paint.getLooper();
1348 if (drawLooper != defaultPaint.getLooper())
1349 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1350 "{kDrawLooper, %p}, ", drawLooper);
1351 SkDebugf("%s{0}};\n", pBuffer);
1352 bufferPtr = pBuffer;
1353 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1354 "PaintScalars paintScalars%p = {", &paint);
1355 SkScalar textSize = paint.getTextSize();
1356 if (textSize != defaultPaint.getTextSize())
1357 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1358 "{kTextSize, %g}, ", SkScalarToFloat(textSize));
1359 SkScalar textScaleX = paint.getTextScaleX();
1360 if (textScaleX != defaultPaint.getTextScaleX())
1361 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1362 "{kTextScaleX, %g}, ", SkScalarToFloat(textScaleX));
1363 SkScalar textSkewX = paint.getTextSkewX();
1364 if (textSkewX != defaultPaint.getTextSkewX())
1365 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1366 "{kTextSkewX, %g}, ", SkScalarToFloat(textSkewX));
1367 SkScalar strokeWidth = paint.getStrokeWidth();
1368 if (strokeWidth != defaultPaint.getStrokeWidth())
1369 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1370 "{kStrokeWidth, %g}, ", SkScalarToFloat(strokeWidth));
1371 SkScalar strokeMiter = paint.getStrokeMiter();
1372 if (strokeMiter != defaultPaint.getStrokeMiter())
1373 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1374 "{kStrokeMiter, %g}, ", SkScalarToFloat(strokeMiter));
1375 SkDebugf("%s{0}};\n", pBuffer);
1376 bufferPtr = pBuffer;
1377 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1378 "PaintInts = paintInts%p = {", &paint);
1379 unsigned color = paint.getColor();
1380 if (color != defaultPaint.getColor())
1381 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1382 "{kColor, 0x%x}, ", color);
1383 unsigned flags = paint.getFlags();
1384 if (flags != defaultPaint.getFlags())
1385 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1386 "{kFlags, 0x%x}, ", flags);
1387 int align = paint.getTextAlign();
1388 if (align != defaultPaint.getTextAlign())
1389 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1390 "{kAlign, 0x%x}, ", align);
1391 int strokeCap = paint.getStrokeCap();
1392 if (strokeCap != defaultPaint.getStrokeCap())
1393 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1394 "{kStrokeCap, 0x%x}, ", strokeCap);
1395 int strokeJoin = paint.getStrokeJoin();
1396 if (strokeJoin != defaultPaint.getStrokeJoin())
1397 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1398 "{kAlign, 0x%x}, ", strokeJoin);
1399 int style = paint.getStyle();
1400 if (style != defaultPaint.getStyle())
1401 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1402 "{kStyle, 0x%x}, ", style);
1403 int textEncoding = paint.getTextEncoding();
1404 if (textEncoding != defaultPaint.getTextEncoding())
1405 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1406 "{kTextEncoding, 0x%x}, ", textEncoding);
1407 SkDebugf("%s{0}};\n", pBuffer);
1409 SkDebugf("PaintData paint%p = {paintPtrs%p, paintScalars%p, paintInts%p};\n",
1410 &paint, &paint, &paint, &paint);
1413 void SkPicturePlayback::dumpPath(const SkPath& path) const {
1414 SkDebugf("path dump unimplemented\n");
1417 void SkPicturePlayback::dumpPicture(const SkPicture& picture) const {
1418 SkDebugf("picture dump unimplemented\n");
1421 void SkPicturePlayback::dumpRegion(const SkRegion& region) const {
1422 SkDebugf("region dump unimplemented\n");
1425 int SkPicturePlayback::dumpDrawType(char* bufferPtr, char* buffer, DrawType drawType) {
1426 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1427 "k%s, ", DrawTypeToString(drawType));
1430 int SkPicturePlayback::dumpInt(char* bufferPtr, char* buffer, char* name) {
1431 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1432 "%s:%d, ", name, getInt());
1435 int SkPicturePlayback::dumpRect(char* bufferPtr, char* buffer, char* name) {
1436 const SkRect* rect = fReader.skipRect();
1437 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1438 "%s:{l:%g t:%g r:%g b:%g}, ", name, SkScalarToFloat(rect.fLeft),
1439 SkScalarToFloat(rect.fTop),
1440 SkScalarToFloat(rect.fRight), SkScalarToFloat(rect.fBottom));
1443 int SkPicturePlayback::dumpPoint(char* bufferPtr, char* buffer, char* name) {
1446 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1447 "%s:{x:%g y:%g}, ", name, SkScalarToFloat(pt.fX),
1448 SkScalarToFloat(pt.fY));
1451 void SkPicturePlayback::dumpPointArray(char** bufferPtrPtr, char* buffer, int count) {
1452 char* bufferPtr = *bufferPtrPtr;
1453 const SkPoint* pts = (const SkPoint*)fReadStream.getAtPos();
1454 fReadStream.skip(sizeof(SkPoint) * count);
1455 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1456 "count:%d {", count);
1457 for (int index = 0; index < count; index++)
1458 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1459 "{x:%g y:%g}, ", SkScalarToFloat(pts[index].fX),
1460 SkScalarToFloat(pts[index].fY));
1461 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1463 *bufferPtrPtr = bufferPtr;
1466 int SkPicturePlayback::dumpPtr(char* bufferPtr, char* buffer, char* name, void* ptr) {
1467 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1468 "%s:%p, ", name, ptr);
1471 int SkPicturePlayback::dumpRectPtr(char* bufferPtr, char* buffer, char* name) {
1473 fReadStream.read(&result, sizeof(result));
1475 return dumpRect(bufferPtr, buffer, name);
1477 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1481 int SkPicturePlayback::dumpScalar(char* bufferPtr, char* buffer, char* name) {
1482 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer),
1483 "%s:%d, ", name, getScalar());
1486 void SkPicturePlayback::dumpText(char** bufferPtrPtr, char* buffer) {
1487 char* bufferPtr = *bufferPtrPtr;
1488 int length = getInt();
1489 bufferPtr += dumpDrawType(bufferPtr, buffer);
1490 fReadStream.skipToAlign4();
1491 char* text = (char*) fReadStream.getAtPos();
1492 fReadStream.skip(length);
1493 bufferPtr += dumpInt(bufferPtr, buffer, "length");
1494 int limit = DUMP_BUFFER_SIZE - (bufferPtr - buffer) - 2;
1500 for (int index = 0; index < limit; index++) {
1501 *bufferPtr++ = *(unsigned short*) text;
1502 text += sizeof(unsigned short);
1506 *bufferPtrPtr = bufferPtr;
1509 #define DUMP_DRAWTYPE(drawType) \
1510 bufferPtr += dumpDrawType(bufferPtr, buffer, drawType)
1512 #define DUMP_INT(name) \
1513 bufferPtr += dumpInt(bufferPtr, buffer, #name)
1515 #define DUMP_RECT_PTR(name) \
1516 bufferPtr += dumpRectPtr(bufferPtr, buffer, #name)
1518 #define DUMP_POINT(name) \
1519 bufferPtr += dumpRect(bufferPtr, buffer, #name)
1521 #define DUMP_RECT(name) \
1522 bufferPtr += dumpRect(bufferPtr, buffer, #name)
1524 #define DUMP_POINT_ARRAY(count) \
1525 dumpPointArray(&bufferPtr, buffer, count)
1527 #define DUMP_PTR(name, ptr) \
1528 bufferPtr += dumpPtr(bufferPtr, buffer, #name, (void*) ptr)
1530 #define DUMP_SCALAR(name) \
1531 bufferPtr += dumpScalar(bufferPtr, buffer, #name)
1533 #define DUMP_TEXT() \
1534 dumpText(&bufferPtr, buffer)
1536 void SkPicturePlayback::dumpStream() {
1537 SkDebugf("RecordStream stream = {\n");
1540 fReadStream.rewind();
1541 char buffer[DUMP_BUFFER_SIZE], * bufferPtr;
1542 while (fReadStream.read(&drawType, sizeof(drawType))) {
1544 DUMP_DRAWTYPE(drawType);
1547 DUMP_PTR(SkPath, &getPath());
1548 DUMP_INT(SkRegion::Op);
1549 DUMP_INT(offsetToRestore);
1552 DUMP_INT(SkRegion::Op);
1553 DUMP_INT(offsetToRestore);
1557 DUMP_INT(SkRegion::Op);
1558 DUMP_INT(offsetToRestore);
1563 DUMP_PTR(SkPaint, getPaint());
1564 DUMP_PTR(SkBitmap, &getBitmap());
1569 DUMP_PTR(SkPaint, getPaint());
1572 DUMP_PTR(SkPaint, getPaint());
1573 DUMP_PTR(SkPath, &getPath());
1575 case DRAW_PICTURE: {
1576 DUMP_PTR(SkPicture, &getPicture());
1579 DUMP_PTR(SkPaint, getPaint());
1580 (void)getInt(); // PointMode
1581 size_t count = getInt();
1582 fReadStream.skipToAlign4();
1583 DUMP_POINT_ARRAY(count);
1585 case DRAW_POS_TEXT: {
1586 DUMP_PTR(SkPaint, getPaint());
1588 size_t points = getInt();
1589 fReadStream.skipToAlign4();
1590 DUMP_POINT_ARRAY(points);
1592 case DRAW_POS_TEXT_H: {
1593 DUMP_PTR(SkPaint, getPaint());
1595 size_t points = getInt();
1596 fReadStream.skipToAlign4();
1598 DUMP_SCALAR(bottom);
1599 DUMP_SCALAR(constY);
1600 DUMP_POINT_ARRAY(points);
1603 DUMP_PTR(SkPaint, getPaint());
1607 DUMP_PTR(SkPaint, getPaint());
1608 DUMP_PTR(SkBitmap, &getBitmap());
1613 DUMP_PTR(SkPaint, getPaint());
1618 case DRAW_TEXT_ON_PATH: {
1619 DUMP_PTR(SkPaint, getPaint());
1621 DUMP_PTR(SkPath, &getPath());
1626 DUMP_SCALAR(rotate);
1629 DUMP_INT(SkCanvas::SaveFlags);
1632 DUMP_RECT_PTR(layer);
1633 DUMP_PTR(SkPaint, getPaint());
1634 DUMP_INT(SkCanvas::SaveFlags);
1651 SkDebugf("%s\n", buffer);
1655 void SkPicturePlayback::dump() const {
1656 char pBuffer[DUMP_BUFFER_SIZE];
1657 char* bufferPtr = pBuffer;
1659 if (fBitmapCount > 0)
1660 SkDebugf("// bitmaps (%d)\n", fBitmapCount);
1661 for (index = 0; index < fBitmapCount; index++) {
1662 const SkBitmap& bitmap = fBitmaps[index];
1665 if (fBitmapCount > 0)
1666 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1667 "Bitmaps bitmaps = {");
1668 for (index = 0; index < fBitmapCount; index++)
1669 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1670 "bitmap%p, ", &fBitmaps[index]);
1671 if (fBitmapCount > 0)
1672 SkDebugf("%s0};\n", pBuffer);
1675 if (fPaintCount > 0)
1676 SkDebugf("// paints (%d)\n", fPaintCount);
1677 for (index = 0; index < fPaintCount; index++) {
1678 const SkPaint& paint = fPaints[index];
1681 bufferPtr = pBuffer;
1682 if (fPaintCount > 0)
1683 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1684 "Paints paints = {");
1685 for (index = 0; index < fPaintCount; index++)
1686 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1687 "paint%p, ", &fPaints[index]);
1688 if (fPaintCount > 0)
1689 SkDebugf("%s0};\n", pBuffer);
1691 for (index = 0; index < fPathCount; index++) {
1692 const SkPath& path = fPaths[index];
1695 bufferPtr = pBuffer;
1697 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1699 for (index = 0; index < fPathCount; index++)
1700 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1701 "path%p, ", &fPaths[index]);
1703 SkDebugf("%s0};\n", pBuffer);
1705 for (index = 0; index < fPictureCount; index++) {
1706 dumpPicture(*fPictureRefs[index]);
1708 bufferPtr = pBuffer;
1709 if (fPictureCount > 0)
1710 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1711 "Pictures pictures = {");
1712 for (index = 0; index < fPictureCount; index++)
1713 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
1714 "picture%p, ", fPictureRefs[index]);
1715 if (fPictureCount > 0)
1716 SkDebugf("%s0};\n", pBuffer);
1718 const_cast<SkPicturePlayback*>(this)->dumpStream();