1/* 2 * Copyright 2011 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7#include <new> 8#include "SkBBoxHierarchy.h" 9#include "SkPicturePlayback.h" 10#include "SkPictureRecord.h" 11#include "SkPictureStateTree.h" 12#include "SkReadBuffer.h" 13#include "SkTypeface.h" 14#include "SkTSort.h" 15#include "SkWriteBuffer.h" 16 17#if SK_SUPPORT_GPU 18#include "GrContext.h" 19#endif 20 21template <typename T> int SafeCount(const T* obj) { 22 return obj ? obj->count() : 0; 23} 24 25/* Define this to spew out a debug statement whenever we skip the remainder of 26 a save/restore block because a clip... command returned false (empty). 27 */ 28#define SPEW_CLIP_SKIPPINGx 29 30SkPicturePlayback::PlaybackReplacements::ReplacementInfo* 31SkPicturePlayback::PlaybackReplacements::push() { 32 SkDEBUGCODE(this->validate()); 33 return fReplacements.push(); 34} 35 36void SkPicturePlayback::PlaybackReplacements::freeAll() { 37 for (int i = 0; i < fReplacements.count(); ++i) { 38 SkDELETE(fReplacements[i].fBM); 39 } 40 fReplacements.reset(); 41} 42 43#ifdef SK_DEBUG 44void SkPicturePlayback::PlaybackReplacements::validate() const { 45 // Check that the ranges are monotonically increasing and non-overlapping 46 if (fReplacements.count() > 0) { 47 SkASSERT(fReplacements[0].fStart < fReplacements[0].fStop); 48 49 for (int i = 1; i < fReplacements.count(); ++i) { 50 SkASSERT(fReplacements[i].fStart < fReplacements[i].fStop); 51 SkASSERT(fReplacements[i-1].fStop < fReplacements[i].fStart); 52 } 53 } 54} 55#endif 56 57SkPicturePlayback::SkPicturePlayback(const SkPictInfo& info) 58 : fInfo(info) { 59 this->init(); 60} 61 62void SkPicturePlayback::initForPlayback() const { 63 // ensure that the paths bounds are pre-computed 64 if (NULL != fPathHeap.get()) { 65 for (int i = 0; i < fPathHeap->count(); i++) { 66 (*fPathHeap.get())[i].updateBoundsCache(); 67 } 68 } 69} 70 71SkPicturePlayback::SkPicturePlayback(const SkPictureRecord& record, 72 const SkPictInfo& info, 73 bool deepCopyOps) 74 : fInfo(info) { 75#ifdef SK_DEBUG_SIZE 76 size_t overallBytes, bitmapBytes, matricesBytes, 77 paintBytes, pathBytes, pictureBytes, regionBytes; 78 int bitmaps = record.bitmaps(&bitmapBytes); 79 int matrices = record.matrices(&matricesBytes); 80 int paints = record.paints(&paintBytes); 81 int paths = record.paths(&pathBytes); 82 int pictures = record.pictures(&pictureBytes); 83 int regions = record.regions(®ionBytes); 84 SkDebugf("picture record mem used %zd (stream %zd) ", record.size(), 85 record.streamlen()); 86 if (bitmaps != 0) 87 SkDebugf("bitmaps size %zd (bitmaps:%d) ", bitmapBytes, bitmaps); 88 if (matrices != 0) 89 SkDebugf("matrices size %zd (matrices:%d) ", matricesBytes, matrices); 90 if (paints != 0) 91 SkDebugf("paints size %zd (paints:%d) ", paintBytes, paints); 92 if (paths != 0) 93 SkDebugf("paths size %zd (paths:%d) ", pathBytes, paths); 94 if (pictures != 0) 95 SkDebugf("pictures size %zd (pictures:%d) ", pictureBytes, pictures); 96 if (regions != 0) 97 SkDebugf("regions size %zd (regions:%d) ", regionBytes, regions); 98 if (record.fPointWrites != 0) 99 SkDebugf("points size %zd (points:%d) ", record.fPointBytes, record.fPointWrites); 100 if (record.fRectWrites != 0) 101 SkDebugf("rects size %zd (rects:%d) ", record.fRectBytes, record.fRectWrites); 102 if (record.fTextWrites != 0) 103 SkDebugf("text size %zd (text strings:%d) ", record.fTextBytes, record.fTextWrites); 104 105 SkDebugf("\n"); 106#endif 107#ifdef SK_DEBUG_DUMP 108 record.dumpMatrices(); 109 record.dumpPaints(); 110#endif 111 112 this->init(); 113 114 fOpData = record.opData(deepCopyOps); 115 116 fBoundingHierarchy = record.fBoundingHierarchy; 117 fStateTree = record.fStateTree; 118 119 SkSafeRef(fBoundingHierarchy); 120 SkSafeRef(fStateTree); 121 fContentInfo.set(record.fContentInfo); 122 123 if (NULL != fBoundingHierarchy) { 124 fBoundingHierarchy->flushDeferredInserts(); 125 } 126 127 // copy over the refcnt dictionary to our reader 128 record.fFlattenableHeap.setupPlaybacks(); 129 130 fBitmaps = record.fBitmapHeap->extractBitmaps(); 131 fPaints = record.fPaints.unflattenToArray(); 132 133 fBitmapHeap.reset(SkSafeRef(record.fBitmapHeap)); 134 fPathHeap.reset(SkSafeRef(record.pathHeap())); 135 136 this->initForPlayback(); 137 138 const SkTDArray<const SkPicture* >& pictures = record.getPictureRefs(); 139 fPictureCount = pictures.count(); 140 if (fPictureCount > 0) { 141 fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount); 142 for (int i = 0; i < fPictureCount; i++) { 143 fPictureRefs[i] = pictures[i]; 144 fPictureRefs[i]->ref(); 145 } 146 } 147 148#ifdef SK_DEBUG_SIZE 149 int overall = fPlayback->size(&overallBytes); 150 bitmaps = fPlayback->bitmaps(&bitmapBytes); 151 paints = fPlayback->paints(&paintBytes); 152 paths = fPlayback->paths(&pathBytes); 153 pictures = fPlayback->pictures(&pictureBytes); 154 regions = fPlayback->regions(®ionBytes); 155 SkDebugf("playback size %zd (objects:%d) ", overallBytes, overall); 156 if (bitmaps != 0) 157 SkDebugf("bitmaps size %zd (bitmaps:%d) ", bitmapBytes, bitmaps); 158 if (paints != 0) 159 SkDebugf("paints size %zd (paints:%d) ", paintBytes, paints); 160 if (paths != 0) 161 SkDebugf("paths size %zd (paths:%d) ", pathBytes, paths); 162 if (pictures != 0) 163 SkDebugf("pictures size %zd (pictures:%d) ", pictureBytes, pictures); 164 if (regions != 0) 165 SkDebugf("regions size %zd (regions:%d) ", regionBytes, regions); 166 SkDebugf("\n"); 167#endif 168} 169 170SkPicturePlayback::SkPicturePlayback(const SkPicturePlayback& src, SkPictCopyInfo* deepCopyInfo) 171 : fInfo(src.fInfo) { 172 this->init(); 173 174 fBitmapHeap.reset(SkSafeRef(src.fBitmapHeap.get())); 175 fPathHeap.reset(SkSafeRef(src.fPathHeap.get())); 176 177 fOpData = SkSafeRef(src.fOpData); 178 179 fBoundingHierarchy = src.fBoundingHierarchy; 180 fStateTree = src.fStateTree; 181 fContentInfo.set(src.fContentInfo); 182 183 SkSafeRef(fBoundingHierarchy); 184 SkSafeRef(fStateTree); 185 186 if (deepCopyInfo) { 187 SkASSERT(deepCopyInfo->initialized); 188 189 int paintCount = SafeCount(src.fPaints); 190 191 if (src.fBitmaps) { 192 fBitmaps = SkTRefArray<SkBitmap>::Create(src.fBitmaps->begin(), src.fBitmaps->count()); 193 } 194 195 fPaints = SkTRefArray<SkPaint>::Create(paintCount); 196 SkASSERT(deepCopyInfo->paintData.count() == paintCount); 197 SkBitmapHeap* bmHeap = deepCopyInfo->controller.getBitmapHeap(); 198 SkTypefacePlayback* tfPlayback = deepCopyInfo->controller.getTypefacePlayback(); 199 for (int i = 0; i < paintCount; i++) { 200 if (deepCopyInfo->paintData[i]) { 201 deepCopyInfo->paintData[i]->unflatten<SkPaint::FlatteningTraits>( 202 &fPaints->writableAt(i), bmHeap, tfPlayback); 203 } else { 204 // needs_deep_copy was false, so just need to assign 205 fPaints->writableAt(i) = src.fPaints->at(i); 206 } 207 } 208 209 } else { 210 fBitmaps = SkSafeRef(src.fBitmaps); 211 fPaints = SkSafeRef(src.fPaints); 212 } 213 214 fPictureCount = src.fPictureCount; 215 fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount); 216 for (int i = 0; i < fPictureCount; i++) { 217 if (deepCopyInfo) { 218 fPictureRefs[i] = src.fPictureRefs[i]->clone(); 219 } else { 220 fPictureRefs[i] = src.fPictureRefs[i]; 221 fPictureRefs[i]->ref(); 222 } 223 } 224} 225 226void SkPicturePlayback::init() { 227 fBitmaps = NULL; 228 fPaints = NULL; 229 fPictureRefs = NULL; 230 fPictureCount = 0; 231 fOpData = NULL; 232 fFactoryPlayback = NULL; 233 fBoundingHierarchy = NULL; 234 fStateTree = NULL; 235 fCachedActiveOps = NULL; 236 fCurOffset = 0; 237 fUseBBH = true; 238 fStart = 0; 239 fStop = 0; 240 fReplacements = NULL; 241} 242 243SkPicturePlayback::~SkPicturePlayback() { 244 SkSafeUnref(fOpData); 245 246 SkSafeUnref(fBitmaps); 247 SkSafeUnref(fPaints); 248 SkSafeUnref(fBoundingHierarchy); 249 SkSafeUnref(fStateTree); 250 251 SkDELETE(fCachedActiveOps); 252 253 for (int i = 0; i < fPictureCount; i++) { 254 fPictureRefs[i]->unref(); 255 } 256 SkDELETE_ARRAY(fPictureRefs); 257 258 SkDELETE(fFactoryPlayback); 259} 260 261void SkPicturePlayback::dumpSize() const { 262 SkDebugf("--- picture size: ops=%d bitmaps=%d [%d] paints=%d [%d]\n", 263 fOpData->size(), 264 SafeCount(fBitmaps), SafeCount(fBitmaps) * sizeof(SkBitmap), 265 SafeCount(fPaints), SafeCount(fPaints) * sizeof(SkPaint)); 266 SkDebugf("--- picture size: paths=%d\n", 267 SafeCount(fPathHeap.get())); 268} 269 270bool SkPicturePlayback::containsBitmaps() const { 271 if (fBitmaps && fBitmaps->count() > 0) { 272 return true; 273 } 274 for (int i = 0; i < fPictureCount; ++i) { 275 if (fPictureRefs[i]->willPlayBackBitmaps()) { 276 return true; 277 } 278 } 279 return false; 280} 281 282/////////////////////////////////////////////////////////////////////////////// 283/////////////////////////////////////////////////////////////////////////////// 284 285#include "SkStream.h" 286 287static size_t compute_chunk_size(SkFlattenable::Factory* array, int count) { 288 size_t size = 4; // for 'count' 289 290 for (int i = 0; i < count; i++) { 291 const char* name = SkFlattenable::FactoryToName(array[i]); 292 if (NULL == name || 0 == *name) { 293 size += SkWStream::SizeOfPackedUInt(0); 294 } else { 295 size_t len = strlen(name); 296 size += SkWStream::SizeOfPackedUInt(len); 297 size += len; 298 } 299 } 300 301 return size; 302} 303 304void SkPicturePlayback::WriteFactories(SkWStream* stream, const SkFactorySet& rec) { 305 int count = rec.count(); 306 307 SkAutoSTMalloc<16, SkFlattenable::Factory> storage(count); 308 SkFlattenable::Factory* array = (SkFlattenable::Factory*)storage.get(); 309 rec.copyToArray(array); 310 311 size_t size = compute_chunk_size(array, count); 312 313 // TODO: write_tag_size should really take a size_t 314 SkPicture::WriteTagSize(stream, SK_PICT_FACTORY_TAG, (uint32_t) size); 315 SkDEBUGCODE(size_t start = stream->bytesWritten()); 316 stream->write32(count); 317 318 for (int i = 0; i < count; i++) { 319 const char* name = SkFlattenable::FactoryToName(array[i]); 320// SkDebugf("---- write factories [%d] %p <%s>\n", i, array[i], name); 321 if (NULL == name || 0 == *name) { 322 stream->writePackedUInt(0); 323 } else { 324 size_t len = strlen(name); 325 stream->writePackedUInt(len); 326 stream->write(name, len); 327 } 328 } 329 330 SkASSERT(size == (stream->bytesWritten() - start)); 331} 332 333void SkPicturePlayback::WriteTypefaces(SkWStream* stream, const SkRefCntSet& rec) { 334 int count = rec.count(); 335 336 SkPicture::WriteTagSize(stream, SK_PICT_TYPEFACE_TAG, count); 337 338 SkAutoSTMalloc<16, SkTypeface*> storage(count); 339 SkTypeface** array = (SkTypeface**)storage.get(); 340 rec.copyToArray((SkRefCnt**)array); 341 342 for (int i = 0; i < count; i++) { 343 array[i]->serialize(stream); 344 } 345} 346 347void SkPicturePlayback::flattenToBuffer(SkWriteBuffer& buffer) const { 348 int i, n; 349 350 if ((n = SafeCount(fBitmaps)) > 0) { 351 SkPicture::WriteTagSize(buffer, SK_PICT_BITMAP_BUFFER_TAG, n); 352 for (i = 0; i < n; i++) { 353 buffer.writeBitmap((*fBitmaps)[i]); 354 } 355 } 356 357 if ((n = SafeCount(fPaints)) > 0) { 358 SkPicture::WriteTagSize(buffer, SK_PICT_PAINT_BUFFER_TAG, n); 359 for (i = 0; i < n; i++) { 360 buffer.writePaint((*fPaints)[i]); 361 } 362 } 363 364 if ((n = SafeCount(fPathHeap.get())) > 0) { 365 SkPicture::WriteTagSize(buffer, SK_PICT_PATH_BUFFER_TAG, n); 366 fPathHeap->flatten(buffer); 367 } 368} 369 370void SkPicturePlayback::serialize(SkWStream* stream, 371 SkPicture::EncodeBitmap encoder) const { 372 SkPicture::WriteTagSize(stream, SK_PICT_READER_TAG, fOpData->size()); 373 stream->write(fOpData->bytes(), fOpData->size()); 374 375 if (fPictureCount > 0) { 376 SkPicture::WriteTagSize(stream, SK_PICT_PICTURE_TAG, fPictureCount); 377 for (int i = 0; i < fPictureCount; i++) { 378 fPictureRefs[i]->serialize(stream, encoder); 379 } 380 } 381 382 // Write some of our data into a writebuffer, and then serialize that 383 // into our stream 384 { 385 SkRefCntSet typefaceSet; 386 SkFactorySet factSet; 387 388 SkWriteBuffer buffer(SkWriteBuffer::kCrossProcess_Flag); 389 buffer.setTypefaceRecorder(&typefaceSet); 390 buffer.setFactoryRecorder(&factSet); 391 buffer.setBitmapEncoder(encoder); 392 393 this->flattenToBuffer(buffer); 394 395 // We have to write these two sets into the stream *before* we write 396 // the buffer, since parsing that buffer will require that we already 397 // have these sets available to use. 398 WriteFactories(stream, factSet); 399 WriteTypefaces(stream, typefaceSet); 400 401 SkPicture::WriteTagSize(stream, SK_PICT_BUFFER_SIZE_TAG, buffer.bytesWritten()); 402 buffer.writeToStream(stream); 403 } 404 405 stream->write32(SK_PICT_EOF_TAG); 406} 407 408void SkPicturePlayback::flatten(SkWriteBuffer& buffer) const { 409 SkPicture::WriteTagSize(buffer, SK_PICT_READER_TAG, fOpData->size()); 410 buffer.writeByteArray(fOpData->bytes(), fOpData->size()); 411 412 if (fPictureCount > 0) { 413 SkPicture::WriteTagSize(buffer, SK_PICT_PICTURE_TAG, fPictureCount); 414 for (int i = 0; i < fPictureCount; i++) { 415 fPictureRefs[i]->flatten(buffer); 416 } 417 } 418 419 // Write this picture playback's data into a writebuffer 420 this->flattenToBuffer(buffer); 421 buffer.write32(SK_PICT_EOF_TAG); 422} 423 424/////////////////////////////////////////////////////////////////////////////// 425 426/** 427 * Return the corresponding SkReadBuffer flags, given a set of 428 * SkPictInfo flags. 429 */ 430static uint32_t pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags) { 431 static const struct { 432 uint32_t fSrc; 433 uint32_t fDst; 434 } gSD[] = { 435 { SkPictInfo::kCrossProcess_Flag, SkReadBuffer::kCrossProcess_Flag }, 436 { SkPictInfo::kScalarIsFloat_Flag, SkReadBuffer::kScalarIsFloat_Flag }, 437 { SkPictInfo::kPtrIs64Bit_Flag, SkReadBuffer::kPtrIs64Bit_Flag }, 438 }; 439 440 uint32_t rbMask = 0; 441 for (size_t i = 0; i < SK_ARRAY_COUNT(gSD); ++i) { 442 if (pictInfoFlags & gSD[i].fSrc) { 443 rbMask |= gSD[i].fDst; 444 } 445 } 446 return rbMask; 447} 448 449bool SkPicturePlayback::parseStreamTag(SkStream* stream, 450 uint32_t tag, 451 uint32_t size, 452 SkPicture::InstallPixelRefProc proc) { 453 /* 454 * By the time we encounter BUFFER_SIZE_TAG, we need to have already seen 455 * its dependents: FACTORY_TAG and TYPEFACE_TAG. These two are not required 456 * but if they are present, they need to have been seen before the buffer. 457 * 458 * We assert that if/when we see either of these, that we have not yet seen 459 * the buffer tag, because if we have, then its too-late to deal with the 460 * factories or typefaces. 461 */ 462 SkDEBUGCODE(bool haveBuffer = false;) 463 464 switch (tag) { 465 case SK_PICT_READER_TAG: { 466 SkAutoMalloc storage(size); 467 if (stream->read(storage.get(), size) != size) { 468 return false; 469 } 470 SkASSERT(NULL == fOpData); 471 fOpData = SkData::NewFromMalloc(storage.detach(), size); 472 } break; 473 case SK_PICT_FACTORY_TAG: { 474 SkASSERT(!haveBuffer); 475 // Remove this code when v21 and below are no longer supported. At the 476 // same time add a new 'count' variable and use it rather then reusing 'size'. 477#ifndef DISABLE_V21_COMPATIBILITY_CODE 478 if (fInfo.fVersion >= 22) { 479 // in v22 this tag's size represents the size of the chunk in bytes 480 // and the number of factory strings is written out separately 481#endif 482 size = stream->readU32(); 483#ifndef DISABLE_V21_COMPATIBILITY_CODE 484 } 485#endif 486 fFactoryPlayback = SkNEW_ARGS(SkFactoryPlayback, (size)); 487 for (size_t i = 0; i < size; i++) { 488 SkString str; 489 const size_t len = stream->readPackedUInt(); 490 str.resize(len); 491 if (stream->read(str.writable_str(), len) != len) { 492 return false; 493 } 494 fFactoryPlayback->base()[i] = SkFlattenable::NameToFactory(str.c_str()); 495 } 496 } break; 497 case SK_PICT_TYPEFACE_TAG: { 498 SkASSERT(!haveBuffer); 499 const int count = SkToInt(size); 500 fTFPlayback.setCount(count); 501 for (int i = 0; i < count; i++) { 502 SkAutoTUnref<SkTypeface> tf(SkTypeface::Deserialize(stream)); 503 if (!tf.get()) { // failed to deserialize 504 // fTFPlayback asserts it never has a null, so we plop in 505 // the default here. 506 tf.reset(SkTypeface::RefDefault()); 507 } 508 fTFPlayback.set(i, tf); 509 } 510 } break; 511 case SK_PICT_PICTURE_TAG: { 512 fPictureCount = size; 513 fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount); 514 bool success = true; 515 int i = 0; 516 for ( ; i < fPictureCount; i++) { 517 fPictureRefs[i] = SkPicture::CreateFromStream(stream, proc); 518 if (NULL == fPictureRefs[i]) { 519 success = false; 520 break; 521 } 522 } 523 if (!success) { 524 // Delete all of the pictures that were already created (up to but excluding i): 525 for (int j = 0; j < i; j++) { 526 fPictureRefs[j]->unref(); 527 } 528 // Delete the array 529 SkDELETE_ARRAY(fPictureRefs); 530 fPictureCount = 0; 531 return false; 532 } 533 } break; 534 case SK_PICT_BUFFER_SIZE_TAG: { 535 SkAutoMalloc storage(size); 536 if (stream->read(storage.get(), size) != size) { 537 return false; 538 } 539 540 SkReadBuffer buffer(storage.get(), size); 541 buffer.setFlags(pictInfoFlagsToReadBufferFlags(fInfo.fFlags)); 542 buffer.setVersion(fInfo.fVersion); 543 544 fFactoryPlayback->setupBuffer(buffer); 545 fTFPlayback.setupBuffer(buffer); 546 buffer.setBitmapDecoder(proc); 547 548 while (!buffer.eof()) { 549 tag = buffer.readUInt(); 550 size = buffer.readUInt(); 551 if (!this->parseBufferTag(buffer, tag, size)) { 552 return false; 553 } 554 } 555 SkDEBUGCODE(haveBuffer = true;) 556 } break; 557 } 558 return true; // success 559} 560 561bool SkPicturePlayback::parseBufferTag(SkReadBuffer& buffer, 562 uint32_t tag, uint32_t size) { 563 switch (tag) { 564 case SK_PICT_BITMAP_BUFFER_TAG: { 565 const int count = SkToInt(size); 566 fBitmaps = SkTRefArray<SkBitmap>::Create(size); 567 for (int i = 0; i < count; ++i) { 568 SkBitmap* bm = &fBitmaps->writableAt(i); 569 buffer.readBitmap(bm); 570 bm->setImmutable(); 571 } 572 } break; 573 case SK_PICT_PAINT_BUFFER_TAG: { 574 const int count = SkToInt(size); 575 fPaints = SkTRefArray<SkPaint>::Create(size); 576 for (int i = 0; i < count; ++i) { 577 buffer.readPaint(&fPaints->writableAt(i)); 578 } 579 } break; 580 case SK_PICT_PATH_BUFFER_TAG: 581 if (size > 0) { 582 fPathHeap.reset(SkNEW_ARGS(SkPathHeap, (buffer))); 583 } 584 break; 585 case SK_PICT_READER_TAG: { 586 SkAutoMalloc storage(size); 587 if (!buffer.readByteArray(storage.get(), size) || 588 !buffer.validate(NULL == fOpData)) { 589 return false; 590 } 591 SkASSERT(NULL == fOpData); 592 fOpData = SkData::NewFromMalloc(storage.detach(), size); 593 } break; 594 case SK_PICT_PICTURE_TAG: { 595 if (!buffer.validate((0 == fPictureCount) && (NULL == fPictureRefs))) { 596 return false; 597 } 598 fPictureCount = size; 599 fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount); 600 bool success = true; 601 int i = 0; 602 for ( ; i < fPictureCount; i++) { 603 fPictureRefs[i] = SkPicture::CreateFromBuffer(buffer); 604 if (NULL == fPictureRefs[i]) { 605 success = false; 606 break; 607 } 608 } 609 if (!success) { 610 // Delete all of the pictures that were already created (up to but excluding i): 611 for (int j = 0; j < i; j++) { 612 fPictureRefs[j]->unref(); 613 } 614 // Delete the array 615 SkDELETE_ARRAY(fPictureRefs); 616 fPictureCount = 0; 617 return false; 618 } 619 } break; 620 default: 621 // The tag was invalid. 622 return false; 623 } 624 return true; // success 625} 626 627SkPicturePlayback* SkPicturePlayback::CreateFromStream(SkStream* stream, 628 const SkPictInfo& info, 629 SkPicture::InstallPixelRefProc proc) { 630 SkAutoTDelete<SkPicturePlayback> playback(SkNEW_ARGS(SkPicturePlayback, (info))); 631 632 if (!playback->parseStream(stream, proc)) { 633 return NULL; 634 } 635 return playback.detach(); 636} 637 638SkPicturePlayback* SkPicturePlayback::CreateFromBuffer(SkReadBuffer& buffer, 639 const SkPictInfo& info) { 640 SkAutoTDelete<SkPicturePlayback> playback(SkNEW_ARGS(SkPicturePlayback, (info))); 641 buffer.setVersion(info.fVersion); 642 643 if (!playback->parseBuffer(buffer)) { 644 return NULL; 645 } 646 return playback.detach(); 647} 648 649bool SkPicturePlayback::parseStream(SkStream* stream, 650 SkPicture::InstallPixelRefProc proc) { 651 for (;;) { 652 uint32_t tag = stream->readU32(); 653 if (SK_PICT_EOF_TAG == tag) { 654 break; 655 } 656 657 uint32_t size = stream->readU32(); 658 if (!this->parseStreamTag(stream, tag, size, proc)) { 659 return false; // we're invalid 660 } 661 } 662 return true; 663} 664 665bool SkPicturePlayback::parseBuffer(SkReadBuffer& buffer) { 666 for (;;) { 667 uint32_t tag = buffer.readUInt(); 668 if (SK_PICT_EOF_TAG == tag) { 669 break; 670 } 671 672 uint32_t size = buffer.readUInt(); 673 if (!this->parseBufferTag(buffer, tag, size)) { 674 return false; // we're invalid 675 } 676 } 677 return true; 678} 679 680/////////////////////////////////////////////////////////////////////////////// 681/////////////////////////////////////////////////////////////////////////////// 682 683#ifdef SPEW_CLIP_SKIPPING 684struct SkipClipRec { 685 int fCount; 686 size_t fSize; 687 688 SkipClipRec() { 689 fCount = 0; 690 fSize = 0; 691 } 692 693 void recordSkip(size_t bytes) { 694 fCount += 1; 695 fSize += bytes; 696 } 697}; 698#endif 699 700#ifdef SK_DEVELOPER 701bool SkPicturePlayback::preDraw(int opIndex, int type) { 702 return false; 703} 704 705void SkPicturePlayback::postDraw(int opIndex) { 706} 707#endif 708 709/* 710 * Read the next op code and chunk size from 'reader'. The returned size 711 * is the entire size of the chunk (including the opcode). Thus, the 712 * offset just prior to calling read_op_and_size + 'size' is the offset 713 * to the next chunk's op code. This also means that the size of a chunk 714 * with no arguments (just an opcode) will be 4. 715 */ 716static DrawType read_op_and_size(SkReader32* reader, uint32_t* size) { 717 uint32_t temp = reader->readInt(); 718 uint32_t op; 719 if (((uint8_t) temp) == temp) { 720 // old skp file - no size information 721 op = temp; 722 *size = 0; 723 } else { 724 UNPACK_8_24(temp, op, *size); 725 if (MASK_24 == *size) { 726 *size = reader->readInt(); 727 } 728 } 729 return (DrawType) op; 730} 731 732uint32_t SkPicturePlayback::CachedOperationList::offset(int index) const { 733 SkASSERT(index < fOps.count()); 734 return ((SkPictureStateTree::Draw*)fOps[index])->fOffset; 735} 736 737const SkMatrix& SkPicturePlayback::CachedOperationList::matrix(int index) const { 738 SkASSERT(index < fOps.count()); 739 return *((SkPictureStateTree::Draw*)fOps[index])->fMatrix; 740} 741 742const SkPicture::OperationList& SkPicturePlayback::getActiveOps(const SkIRect& query) { 743 if (NULL == fStateTree || NULL == fBoundingHierarchy) { 744 return SkPicture::OperationList::InvalidList(); 745 } 746 747 if (NULL == fCachedActiveOps) { 748 fCachedActiveOps = SkNEW(CachedOperationList); 749 } 750 751 if (query == fCachedActiveOps->fCacheQueryRect) { 752 return *fCachedActiveOps; 753 } 754 755 fCachedActiveOps->fOps.rewind(); 756 757 fBoundingHierarchy->search(query, &(fCachedActiveOps->fOps)); 758 if (0 != fCachedActiveOps->fOps.count()) { 759 SkTQSort<SkPictureStateTree::Draw>( 760 reinterpret_cast<SkPictureStateTree::Draw**>(fCachedActiveOps->fOps.begin()), 761 reinterpret_cast<SkPictureStateTree::Draw**>(fCachedActiveOps->fOps.end()-1)); 762 } 763 764 fCachedActiveOps->fCacheQueryRect = query; 765 return *fCachedActiveOps; 766} 767 768class SkAutoResetOpID { 769public: 770 SkAutoResetOpID(SkPicturePlayback* playback) : fPlayback(playback) { } 771 ~SkAutoResetOpID() { 772 if (NULL != fPlayback) { 773 fPlayback->resetOpID(); 774 } 775 } 776 777private: 778 SkPicturePlayback* fPlayback; 779}; 780 781// TODO: Replace with hash or pass in "lastLookedUp" hint 782SkPicturePlayback::PlaybackReplacements::ReplacementInfo* 783SkPicturePlayback::PlaybackReplacements::lookupByStart(size_t start) { 784 SkDEBUGCODE(this->validate()); 785 for (int i = 0; i < fReplacements.count(); ++i) { 786 if (start == fReplacements[i].fStart) { 787 return &fReplacements[i]; 788 } else if (start < fReplacements[i].fStart) { 789 return NULL; // the ranges are monotonically increasing and non-overlapping 790 } 791 } 792 793 return NULL; 794} 795 796void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback) { 797 SkAutoResetOpID aroi(this); 798 SkASSERT(0 == fCurOffset); 799 800#ifdef ENABLE_TIME_DRAW 801 SkAutoTime at("SkPicture::draw", 50); 802#endif 803 804#ifdef SPEW_CLIP_SKIPPING 805 SkipClipRec skipRect, skipRRect, skipRegion, skipPath, skipCull; 806 int opCount = 0; 807#endif 808 809#ifdef SK_BUILD_FOR_ANDROID 810 SkAutoMutexAcquire autoMutex(fDrawMutex); 811#endif 812 813 // kDrawComplete will be the signal that we have reached the end of 814 // the command stream 815 static const uint32_t kDrawComplete = SK_MaxU32; 816 817 SkReader32 reader(fOpData->bytes(), fOpData->size()); 818 TextContainer text; 819 const SkTDArray<void*>* activeOps = NULL; 820 821 // When draw limits are enabled (i.e., 0 != fStart || 0 != fStop) the state 822 // tree isn't used to pick and choose the draw operations 823 if (0 == fStart && 0 == fStop) { 824 if (fUseBBH && NULL != fStateTree && NULL != fBoundingHierarchy) { 825 SkRect clipBounds; 826 if (canvas.getClipBounds(&clipBounds)) { 827 SkIRect query; 828 clipBounds.roundOut(&query); 829 830 const SkPicture::OperationList& activeOpsList = this->getActiveOps(query); 831 if (activeOpsList.valid()) { 832 if (0 == activeOpsList.numOps()) { 833 return; // nothing to draw 834 } 835 836 // Since the opList is valid we know it is our derived class 837 activeOps = &((const CachedOperationList&)activeOpsList).fOps; 838 } 839 } 840 } 841 } 842 843 SkPictureStateTree::Iterator it = (NULL == activeOps) ? 844 SkPictureStateTree::Iterator() : 845 fStateTree->getIterator(*activeOps, &canvas); 846 847 if (0 != fStart || 0 != fStop) { 848 reader.setOffset(fStart); 849 uint32_t size; 850 SkDEBUGCODE(DrawType op =) read_op_and_size(&reader, &size); 851 SkASSERT(SAVE_LAYER == op); 852 reader.setOffset(fStart+size); 853 } 854 855 if (it.isValid()) { 856 uint32_t skipTo = it.nextDraw(); 857 if (kDrawComplete == skipTo) { 858 return; 859 } 860 reader.setOffset(skipTo); 861 } 862 863 // Record this, so we can concat w/ it if we encounter a setMatrix() 864 SkMatrix initialMatrix = canvas.getTotalMatrix(); 865 866 SkAutoCanvasRestore acr(&canvas, false); 867 868#ifdef SK_BUILD_FOR_ANDROID 869 fAbortCurrentPlayback = false; 870#endif 871 872#ifdef SK_DEVELOPER 873 int opIndex = -1; 874#endif 875 876 while (!reader.eof()) { 877 if (callback && callback->abortDrawing()) { 878 return; 879 } 880#ifdef SK_BUILD_FOR_ANDROID 881 if (fAbortCurrentPlayback) { 882 return; 883 } 884#endif 885 if (0 != fStart || 0 != fStop) { 886 size_t offset = reader.offset() ; 887 if (offset >= fStop) { 888 uint32_t size; 889 SkDEBUGCODE(DrawType op =) read_op_and_size(&reader, &size); 890 SkASSERT(RESTORE == op); 891 return; 892 } 893 } 894 895 if (NULL != fReplacements) { 896 // Potentially replace a block of operations with a single drawBitmap call 897 SkPicturePlayback::PlaybackReplacements::ReplacementInfo* temp = 898 fReplacements->lookupByStart(reader.offset()); 899 if (NULL != temp) { 900 SkASSERT(NULL != temp->fBM); 901 SkASSERT(NULL != temp->fPaint); 902 canvas.save(); 903 canvas.setMatrix(initialMatrix); 904 canvas.drawBitmap(*temp->fBM, temp->fPos.fX, temp->fPos.fY, temp->fPaint); 905 canvas.restore(); 906 907 if (it.isValid()) { 908 // This save is needed since the BBH will automatically issue 909 // a restore to balanced the saveLayer we're skipping 910 canvas.save(); 911 912 // At this point we know that the PictureStateTree was aiming 913 // for some draw op within temp's saveLayer (although potentially 914 // in a separate saveLayer nested inside it). 915 // We need to skip all the operations inside temp's range 916 // along with all the associated state changes but update 917 // the state tree to the first operation outside temp's range. 918 919 uint32_t skipTo; 920 do { 921 skipTo = it.nextDraw(); 922 if (kDrawComplete == skipTo) { 923 break; 924 } 925 926 if (skipTo <= temp->fStop) { 927 reader.setOffset(skipTo); 928 uint32_t size; 929 DrawType op = read_op_and_size(&reader, &size); 930 // Since we are relying on the normal SkPictureStateTree 931 // playback we need to convert any nested saveLayer calls 932 // it may issue into saves (so that all its internal 933 // restores will be balanced). 934 if (SAVE_LAYER == op) { 935 canvas.save(); 936 } 937 } 938 } while (skipTo <= temp->fStop); 939 940 if (kDrawComplete == skipTo) { 941 break; 942 } 943 944 reader.setOffset(skipTo); 945 } else { 946 reader.setOffset(temp->fStop); 947 uint32_t size; 948 SkDEBUGCODE(DrawType op =) read_op_and_size(&reader, &size); 949 SkASSERT(RESTORE == op); 950 } 951 continue; 952 } 953 } 954 955#ifdef SPEW_CLIP_SKIPPING 956 opCount++; 957#endif 958 959 fCurOffset = reader.offset(); 960 uint32_t size; 961 DrawType op = read_op_and_size(&reader, &size); 962 size_t skipTo = 0; 963 if (NOOP == op) { 964 // NOOPs are to be ignored - do not propagate them any further 965 skipTo = fCurOffset + size; 966#ifdef SK_DEVELOPER 967 } else { 968 opIndex++; 969 if (this->preDraw(opIndex, op)) { 970 skipTo = fCurOffset + size; 971 } 972#endif 973 } 974 975 if (0 != skipTo) { 976 if (it.isValid()) { 977 // If using a bounding box hierarchy, advance the state tree 978 // iterator until at or after skipTo 979 uint32_t adjustedSkipTo; 980 do { 981 adjustedSkipTo = it.nextDraw(); 982 } while (adjustedSkipTo < skipTo); 983 skipTo = adjustedSkipTo; 984 } 985 if (kDrawComplete == skipTo) { 986 break; 987 } 988 reader.setOffset(skipTo); 989 continue; 990 } 991 992 switch (op) { 993 case CLIP_PATH: { 994 const SkPath& path = getPath(reader); 995 uint32_t packed = reader.readInt(); 996 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed); 997 bool doAA = ClipParams_unpackDoAA(packed); 998 size_t offsetToRestore = reader.readInt(); 999 SkASSERT(!offsetToRestore || \ 1000 offsetToRestore >= reader.offset()); 1001 canvas.clipPath(path, regionOp, doAA); 1002 if (canvas.isClipEmpty() && offsetToRestore) { 1003#ifdef SPEW_CLIP_SKIPPING 1004 skipPath.recordSkip(offsetToRestore - reader.offset()); 1005#endif 1006 reader.setOffset(offsetToRestore); 1007 } 1008 } break; 1009 case CLIP_REGION: { 1010 SkRegion region; 1011 this->getRegion(reader, ®ion); 1012 uint32_t packed = reader.readInt(); 1013 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed); 1014 size_t offsetToRestore = reader.readInt(); 1015 SkASSERT(!offsetToRestore || \ 1016 offsetToRestore >= reader.offset()); 1017 canvas.clipRegion(region, regionOp); 1018 if (canvas.isClipEmpty() && offsetToRestore) { 1019#ifdef SPEW_CLIP_SKIPPING 1020 skipRegion.recordSkip(offsetToRestore - reader.offset()); 1021#endif 1022 reader.setOffset(offsetToRestore); 1023 } 1024 } break; 1025 case CLIP_RECT: { 1026 const SkRect& rect = reader.skipT<SkRect>(); 1027 uint32_t packed = reader.readInt(); 1028 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed); 1029 bool doAA = ClipParams_unpackDoAA(packed); 1030 size_t offsetToRestore = reader.readInt(); 1031 SkASSERT(!offsetToRestore || \ 1032 offsetToRestore >= reader.offset()); 1033 canvas.clipRect(rect, regionOp, doAA); 1034 if (canvas.isClipEmpty() && offsetToRestore) { 1035#ifdef SPEW_CLIP_SKIPPING 1036 skipRect.recordSkip(offsetToRestore - reader.offset()); 1037#endif 1038 reader.setOffset(offsetToRestore); 1039 } 1040 } break; 1041 case CLIP_RRECT: { 1042 SkRRect rrect; 1043 reader.readRRect(&rrect); 1044 uint32_t packed = reader.readInt(); 1045 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed); 1046 bool doAA = ClipParams_unpackDoAA(packed); 1047 size_t offsetToRestore = reader.readInt(); 1048 SkASSERT(!offsetToRestore || offsetToRestore >= reader.offset()); 1049 canvas.clipRRect(rrect, regionOp, doAA); 1050 if (canvas.isClipEmpty() && offsetToRestore) { 1051#ifdef SPEW_CLIP_SKIPPING 1052 skipRRect.recordSkip(offsetToRestore - reader.offset()); 1053#endif 1054 reader.setOffset(offsetToRestore); 1055 } 1056 } break; 1057 case PUSH_CULL: { 1058 const SkRect& cullRect = reader.skipT<SkRect>(); 1059 size_t offsetToRestore = reader.readInt(); 1060 if (offsetToRestore && canvas.quickReject(cullRect)) { 1061#ifdef SPEW_CLIP_SKIPPING 1062 skipCull.recordSkip(offsetToRestore - reader.offset()); 1063#endif 1064 reader.setOffset(offsetToRestore); 1065 } else { 1066 canvas.pushCull(cullRect); 1067 } 1068 } break; 1069 case POP_CULL: 1070 canvas.popCull(); 1071 break; 1072 case CONCAT: { 1073 SkMatrix matrix; 1074 this->getMatrix(reader, &matrix); 1075 canvas.concat(matrix); 1076 break; 1077 } 1078 case DRAW_BITMAP: { 1079 const SkPaint* paint = this->getPaint(reader); 1080 const SkBitmap& bitmap = this->getBitmap(reader); 1081 const SkPoint& loc = reader.skipT<SkPoint>(); 1082 canvas.drawBitmap(bitmap, loc.fX, loc.fY, paint); 1083 } break; 1084 case DRAW_BITMAP_RECT_TO_RECT: { 1085 const SkPaint* paint = this->getPaint(reader); 1086 const SkBitmap& bitmap = this->getBitmap(reader); 1087 const SkRect* src = this->getRectPtr(reader); // may be null 1088 const SkRect& dst = reader.skipT<SkRect>(); // required 1089 SkCanvas::DrawBitmapRectFlags flags; 1090 flags = (SkCanvas::DrawBitmapRectFlags) reader.readInt(); 1091 canvas.drawBitmapRectToRect(bitmap, src, dst, paint, flags); 1092 } break; 1093 case DRAW_BITMAP_MATRIX: { 1094 const SkPaint* paint = this->getPaint(reader); 1095 const SkBitmap& bitmap = this->getBitmap(reader); 1096 SkMatrix matrix; 1097 this->getMatrix(reader, &matrix); 1098 canvas.drawBitmapMatrix(bitmap, matrix, paint); 1099 } break; 1100 case DRAW_BITMAP_NINE: { 1101 const SkPaint* paint = this->getPaint(reader); 1102 const SkBitmap& bitmap = this->getBitmap(reader); 1103 const SkIRect& src = reader.skipT<SkIRect>(); 1104 const SkRect& dst = reader.skipT<SkRect>(); 1105 canvas.drawBitmapNine(bitmap, src, dst, paint); 1106 } break; 1107 case DRAW_CLEAR: 1108 canvas.clear(reader.readInt()); 1109 break; 1110 case DRAW_DATA: { 1111 size_t length = reader.readInt(); 1112 canvas.drawData(reader.skip(length), length); 1113 // skip handles padding the read out to a multiple of 4 1114 } break; 1115 case DRAW_DRRECT: { 1116 const SkPaint& paint = *this->getPaint(reader); 1117 SkRRect outer, inner; 1118 reader.readRRect(&outer); 1119 reader.readRRect(&inner); 1120 canvas.drawDRRect(outer, inner, paint); 1121 } break; 1122 case BEGIN_COMMENT_GROUP: { 1123 const char* desc = reader.readString(); 1124 canvas.beginCommentGroup(desc); 1125 } break; 1126 case COMMENT: { 1127 const char* kywd = reader.readString(); 1128 const char* value = reader.readString(); 1129 canvas.addComment(kywd, value); 1130 } break; 1131 case END_COMMENT_GROUP: { 1132 canvas.endCommentGroup(); 1133 } break; 1134 case DRAW_OVAL: { 1135 const SkPaint& paint = *this->getPaint(reader); 1136 canvas.drawOval(reader.skipT<SkRect>(), paint); 1137 } break; 1138 case DRAW_PAINT: 1139 canvas.drawPaint(*this->getPaint(reader)); 1140 break; 1141 case DRAW_PATH: { 1142 const SkPaint& paint = *this->getPaint(reader); 1143 canvas.drawPath(getPath(reader), paint); 1144 } break; 1145 case DRAW_PICTURE: 1146 canvas.drawPicture(this->getPicture(reader)); 1147 break; 1148 case DRAW_POINTS: { 1149 const SkPaint& paint = *this->getPaint(reader); 1150 SkCanvas::PointMode mode = (SkCanvas::PointMode)reader.readInt(); 1151 size_t count = reader.readInt(); 1152 const SkPoint* pts = (const SkPoint*)reader.skip(sizeof(SkPoint) * count); 1153 canvas.drawPoints(mode, count, pts, paint); 1154 } break; 1155 case DRAW_POS_TEXT: { 1156 const SkPaint& paint = *this->getPaint(reader); 1157 getText(reader, &text); 1158 size_t points = reader.readInt(); 1159 const SkPoint* pos = (const SkPoint*)reader.skip(points * sizeof(SkPoint)); 1160 canvas.drawPosText(text.text(), text.length(), pos, paint); 1161 } break; 1162 case DRAW_POS_TEXT_TOP_BOTTOM: { 1163 const SkPaint& paint = *this->getPaint(reader); 1164 getText(reader, &text); 1165 size_t points = reader.readInt(); 1166 const SkPoint* pos = (const SkPoint*)reader.skip(points * sizeof(SkPoint)); 1167 const SkScalar top = reader.readScalar(); 1168 const SkScalar bottom = reader.readScalar(); 1169 if (!canvas.quickRejectY(top, bottom)) { 1170 canvas.drawPosText(text.text(), text.length(), pos, paint); 1171 } 1172 } break; 1173 case DRAW_POS_TEXT_H: { 1174 const SkPaint& paint = *this->getPaint(reader); 1175 getText(reader, &text); 1176 size_t xCount = reader.readInt(); 1177 const SkScalar constY = reader.readScalar(); 1178 const SkScalar* xpos = (const SkScalar*)reader.skip(xCount * sizeof(SkScalar)); 1179 canvas.drawPosTextH(text.text(), text.length(), xpos, constY, 1180 paint); 1181 } break; 1182 case DRAW_POS_TEXT_H_TOP_BOTTOM: { 1183 const SkPaint& paint = *this->getPaint(reader); 1184 getText(reader, &text); 1185 size_t xCount = reader.readInt(); 1186 const SkScalar* xpos = (const SkScalar*)reader.skip((3 + xCount) * sizeof(SkScalar)); 1187 const SkScalar top = *xpos++; 1188 const SkScalar bottom = *xpos++; 1189 const SkScalar constY = *xpos++; 1190 if (!canvas.quickRejectY(top, bottom)) { 1191 canvas.drawPosTextH(text.text(), text.length(), xpos, 1192 constY, paint); 1193 } 1194 } break; 1195 case DRAW_RECT: { 1196 const SkPaint& paint = *this->getPaint(reader); 1197 canvas.drawRect(reader.skipT<SkRect>(), paint); 1198 } break; 1199 case DRAW_RRECT: { 1200 const SkPaint& paint = *this->getPaint(reader); 1201 SkRRect rrect; 1202 reader.readRRect(&rrect); 1203 canvas.drawRRect(rrect, paint); 1204 } break; 1205 case DRAW_SPRITE: { 1206 const SkPaint* paint = this->getPaint(reader); 1207 const SkBitmap& bitmap = this->getBitmap(reader); 1208 int left = reader.readInt(); 1209 int top = reader.readInt(); 1210 canvas.drawSprite(bitmap, left, top, paint); 1211 } break; 1212 case DRAW_TEXT: { 1213 const SkPaint& paint = *this->getPaint(reader); 1214 this->getText(reader, &text); 1215 SkScalar x = reader.readScalar(); 1216 SkScalar y = reader.readScalar(); 1217 canvas.drawText(text.text(), text.length(), x, y, paint); 1218 } break; 1219 case DRAW_TEXT_TOP_BOTTOM: { 1220 const SkPaint& paint = *this->getPaint(reader); 1221 this->getText(reader, &text); 1222 const SkScalar* ptr = (const SkScalar*)reader.skip(4 * sizeof(SkScalar)); 1223 // ptr[0] == x 1224 // ptr[1] == y 1225 // ptr[2] == top 1226 // ptr[3] == bottom 1227 if (!canvas.quickRejectY(ptr[2], ptr[3])) { 1228 canvas.drawText(text.text(), text.length(), ptr[0], ptr[1], 1229 paint); 1230 } 1231 } break; 1232 case DRAW_TEXT_ON_PATH: { 1233 const SkPaint& paint = *this->getPaint(reader); 1234 getText(reader, &text); 1235 const SkPath& path = this->getPath(reader); 1236 SkMatrix matrix; 1237 this->getMatrix(reader, &matrix); 1238 canvas.drawTextOnPath(text.text(), text.length(), path, &matrix, paint); 1239 } break; 1240 case DRAW_VERTICES: { 1241 SkAutoTUnref<SkXfermode> xfer; 1242 const SkPaint& paint = *this->getPaint(reader); 1243 DrawVertexFlags flags = (DrawVertexFlags)reader.readInt(); 1244 SkCanvas::VertexMode vmode = (SkCanvas::VertexMode)reader.readInt(); 1245 int vCount = reader.readInt(); 1246 const SkPoint* verts = (const SkPoint*)reader.skip( 1247 vCount * sizeof(SkPoint)); 1248 const SkPoint* texs = NULL; 1249 const SkColor* colors = NULL; 1250 const uint16_t* indices = NULL; 1251 int iCount = 0; 1252 if (flags & DRAW_VERTICES_HAS_TEXS) { 1253 texs = (const SkPoint*)reader.skip( 1254 vCount * sizeof(SkPoint)); 1255 } 1256 if (flags & DRAW_VERTICES_HAS_COLORS) { 1257 colors = (const SkColor*)reader.skip( 1258 vCount * sizeof(SkColor)); 1259 } 1260 if (flags & DRAW_VERTICES_HAS_INDICES) { 1261 iCount = reader.readInt(); 1262 indices = (const uint16_t*)reader.skip( 1263 iCount * sizeof(uint16_t)); 1264 } 1265 if (flags & DRAW_VERTICES_HAS_XFER) { 1266 int mode = reader.readInt(); 1267 if (mode < 0 || mode > SkXfermode::kLastMode) { 1268 mode = SkXfermode::kModulate_Mode; 1269 } 1270 xfer.reset(SkXfermode::Create((SkXfermode::Mode)mode)); 1271 } 1272 canvas.drawVertices(vmode, vCount, verts, texs, colors, xfer, 1273 indices, iCount, paint); 1274 } break; 1275 case RESTORE: 1276 canvas.restore(); 1277 break; 1278 case ROTATE: 1279 canvas.rotate(reader.readScalar()); 1280 break; 1281 case SAVE: 1282 canvas.save((SkCanvas::SaveFlags) reader.readInt()); 1283 break; 1284 case SAVE_LAYER: { 1285 const SkRect* boundsPtr = this->getRectPtr(reader); 1286 const SkPaint* paint = this->getPaint(reader); 1287 canvas.saveLayer(boundsPtr, paint, (SkCanvas::SaveFlags) reader.readInt()); 1288 } break; 1289 case SCALE: { 1290 SkScalar sx = reader.readScalar(); 1291 SkScalar sy = reader.readScalar(); 1292 canvas.scale(sx, sy); 1293 } break; 1294 case SET_MATRIX: { 1295 SkMatrix matrix; 1296 this->getMatrix(reader, &matrix); 1297 matrix.postConcat(initialMatrix); 1298 canvas.setMatrix(matrix); 1299 } break; 1300 case SKEW: { 1301 SkScalar sx = reader.readScalar(); 1302 SkScalar sy = reader.readScalar(); 1303 canvas.skew(sx, sy); 1304 } break; 1305 case TRANSLATE: { 1306 SkScalar dx = reader.readScalar(); 1307 SkScalar dy = reader.readScalar(); 1308 canvas.translate(dx, dy); 1309 } break; 1310 default: 1311 SkASSERT(0); 1312 } 1313 1314#ifdef SK_DEVELOPER 1315 this->postDraw(opIndex); 1316#endif 1317 1318 if (it.isValid()) { 1319 uint32_t skipTo = it.nextDraw(); 1320 if (kDrawComplete == skipTo) { 1321 break; 1322 } 1323 reader.setOffset(skipTo); 1324 } 1325 } 1326 1327#ifdef SPEW_CLIP_SKIPPING 1328 { 1329 size_t size = skipRect.fSize + skipRRect.fSize + skipPath.fSize + skipRegion.fSize + 1330 skipCull.fSize; 1331 SkDebugf("--- Clip skips %d%% rect:%d rrect:%d path:%d rgn:%d cull:%d\n", 1332 size * 100 / reader.offset(), skipRect.fCount, skipRRect.fCount, 1333 skipPath.fCount, skipRegion.fCount, skipCull.fCount); 1334 SkDebugf("--- Total ops: %d\n", opCount); 1335 } 1336#endif 1337// this->dumpSize(); 1338} 1339 1340 1341#if SK_SUPPORT_GPU 1342bool SkPicturePlayback::suitableForGpuRasterization(GrContext* context, const char **reason, 1343 int sampleCount) const { 1344 // TODO: the heuristic used here needs to be refined 1345 static const int kNumPaintWithPathEffectUsesTol = 1; 1346 static const int kNumAAConcavePaths = 5; 1347 1348 SkASSERT(fContentInfo.numAAHairlineConcavePaths() <= fContentInfo.numAAConcavePaths()); 1349 1350 int numNonDashedPathEffects = fContentInfo.numPaintWithPathEffectUses() - 1351 fContentInfo.numFastPathDashEffects(); 1352 1353 bool suitableForDash = (0 == fContentInfo.numPaintWithPathEffectUses()) || 1354 (numNonDashedPathEffects < kNumPaintWithPathEffectUsesTol 1355 && 0 == sampleCount); 1356 1357 bool ret = suitableForDash && 1358 (fContentInfo.numAAConcavePaths() - fContentInfo.numAAHairlineConcavePaths()) 1359 < kNumAAConcavePaths; 1360 if (!ret && NULL != reason) { 1361 if (!suitableForDash) { 1362 if (0 != sampleCount) { 1363 *reason = "Can't use multisample on dash effect."; 1364 } else { 1365 *reason = "Too many non dashed path effects."; 1366 } 1367 } else if ((fContentInfo.numAAConcavePaths() - fContentInfo.numAAHairlineConcavePaths()) 1368 >= kNumAAConcavePaths) 1369 *reason = "Too many anti-aliased concave paths."; 1370 else 1371 *reason = "Unknown reason for GPU unsuitability."; 1372 } 1373 return ret; 1374} 1375 1376bool SkPicturePlayback::suitableForGpuRasterization(GrContext* context, const char **reason, 1377 GrPixelConfig config, SkScalar dpi) const { 1378 1379 if (context != NULL) { 1380 return this->suitableForGpuRasterization(context, reason, 1381 context->getRecommendedSampleCount(config, dpi)); 1382 } else { 1383 return this->suitableForGpuRasterization(NULL, reason); 1384 } 1385} 1386 1387#endif 1388/////////////////////////////////////////////////////////////////////////////// 1389 1390#ifdef SK_DEBUG_SIZE 1391int SkPicturePlayback::size(size_t* sizePtr) { 1392 int objects = bitmaps(sizePtr); 1393 objects += paints(sizePtr); 1394 objects += paths(sizePtr); 1395 objects += pictures(sizePtr); 1396 objects += regions(sizePtr); 1397 *sizePtr = fOpData.size(); 1398 return objects; 1399} 1400 1401int SkPicturePlayback::bitmaps(size_t* size) { 1402 size_t result = 0; 1403 for (int index = 0; index < fBitmapCount; index++) { 1404 // const SkBitmap& bitmap = fBitmaps[index]; 1405 result += sizeof(SkBitmap); // bitmap->size(); 1406 } 1407 *size = result; 1408 return fBitmapCount; 1409} 1410 1411int SkPicturePlayback::paints(size_t* size) { 1412 size_t result = 0; 1413 for (int index = 0; index < fPaintCount; index++) { 1414 // const SkPaint& paint = fPaints[index]; 1415 result += sizeof(SkPaint); // paint->size(); 1416 } 1417 *size = result; 1418 return fPaintCount; 1419} 1420 1421int SkPicturePlayback::paths(size_t* size) { 1422 size_t result = 0; 1423 for (int index = 0; index < fPathCount; index++) { 1424 const SkPath& path = fPaths[index]; 1425 result += path.flatten(NULL); 1426 } 1427 *size = result; 1428 return fPathCount; 1429} 1430#endif 1431 1432#ifdef SK_DEBUG_DUMP 1433void SkPicturePlayback::dumpBitmap(const SkBitmap& bitmap) const { 1434 char pBuffer[DUMP_BUFFER_SIZE]; 1435 char* bufferPtr = pBuffer; 1436 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1437 "BitmapData bitmap%p = {", &bitmap); 1438 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1439 "{kWidth, %d}, ", bitmap.width()); 1440 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1441 "{kHeight, %d}, ", bitmap.height()); 1442 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1443 "{kRowBytes, %d}, ", bitmap.rowBytes()); 1444// start here; 1445 SkDebugf("%s{0}};\n", pBuffer); 1446} 1447 1448void dumpMatrix(const SkMatrix& matrix) const { 1449 SkMatrix defaultMatrix; 1450 defaultMatrix.reset(); 1451 char pBuffer[DUMP_BUFFER_SIZE]; 1452 char* bufferPtr = pBuffer; 1453 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1454 "MatrixData matrix%p = {", &matrix); 1455 SkScalar scaleX = matrix.getScaleX(); 1456 if (scaleX != defaultMatrix.getScaleX()) 1457 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1458 "{kScaleX, %g}, ", SkScalarToFloat(scaleX)); 1459 SkScalar scaleY = matrix.getScaleY(); 1460 if (scaleY != defaultMatrix.getScaleY()) 1461 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1462 "{kScaleY, %g}, ", SkScalarToFloat(scaleY)); 1463 SkScalar skewX = matrix.getSkewX(); 1464 if (skewX != defaultMatrix.getSkewX()) 1465 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1466 "{kSkewX, %g}, ", SkScalarToFloat(skewX)); 1467 SkScalar skewY = matrix.getSkewY(); 1468 if (skewY != defaultMatrix.getSkewY()) 1469 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1470 "{kSkewY, %g}, ", SkScalarToFloat(skewY)); 1471 SkScalar translateX = matrix.getTranslateX(); 1472 if (translateX != defaultMatrix.getTranslateX()) 1473 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1474 "{kTranslateX, %g}, ", SkScalarToFloat(translateX)); 1475 SkScalar translateY = matrix.getTranslateY(); 1476 if (translateY != defaultMatrix.getTranslateY()) 1477 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1478 "{kTranslateY, %g}, ", SkScalarToFloat(translateY)); 1479 SkScalar perspX = matrix.getPerspX(); 1480 if (perspX != defaultMatrix.getPerspX()) 1481 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1482 "{kPerspX, %g}, ", perspX); 1483 SkScalar perspY = matrix.getPerspY(); 1484 if (perspY != defaultMatrix.getPerspY()) 1485 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1486 "{kPerspY, %g}, ", perspY); 1487 SkDebugf("%s{0}};\n", pBuffer); 1488} 1489 1490void dumpPaint(const SkPaint& paint) const { 1491 SkPaint defaultPaint; 1492 char pBuffer[DUMP_BUFFER_SIZE]; 1493 char* bufferPtr = pBuffer; 1494 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1495 "PaintPointers paintPtrs%p = {", &paint); 1496 const SkTypeface* typeface = paint.getTypeface(); 1497 if (typeface != defaultPaint.getTypeface()) 1498 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1499 "{kTypeface, %p}, ", typeface); 1500 const SkPathEffect* pathEffect = paint.getPathEffect(); 1501 if (pathEffect != defaultPaint.getPathEffect()) 1502 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1503 "{kPathEffect, %p}, ", pathEffect); 1504 const SkShader* shader = paint.getShader(); 1505 if (shader != defaultPaint.getShader()) 1506 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1507 "{kShader, %p}, ", shader); 1508 const SkXfermode* xfermode = paint.getXfermode(); 1509 if (xfermode != defaultPaint.getXfermode()) 1510 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1511 "{kXfermode, %p}, ", xfermode); 1512 const SkMaskFilter* maskFilter = paint.getMaskFilter(); 1513 if (maskFilter != defaultPaint.getMaskFilter()) 1514 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1515 "{kMaskFilter, %p}, ", maskFilter); 1516 const SkColorFilter* colorFilter = paint.getColorFilter(); 1517 if (colorFilter != defaultPaint.getColorFilter()) 1518 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1519 "{kColorFilter, %p}, ", colorFilter); 1520 const SkRasterizer* rasterizer = paint.getRasterizer(); 1521 if (rasterizer != defaultPaint.getRasterizer()) 1522 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1523 "{kRasterizer, %p}, ", rasterizer); 1524 const SkDrawLooper* drawLooper = paint.getLooper(); 1525 if (drawLooper != defaultPaint.getLooper()) 1526 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1527 "{kDrawLooper, %p}, ", drawLooper); 1528 SkDebugf("%s{0}};\n", pBuffer); 1529 bufferPtr = pBuffer; 1530 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1531 "PaintScalars paintScalars%p = {", &paint); 1532 SkScalar textSize = paint.getTextSize(); 1533 if (textSize != defaultPaint.getTextSize()) 1534 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1535 "{kTextSize, %g}, ", SkScalarToFloat(textSize)); 1536 SkScalar textScaleX = paint.getTextScaleX(); 1537 if (textScaleX != defaultPaint.getTextScaleX()) 1538 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1539 "{kTextScaleX, %g}, ", SkScalarToFloat(textScaleX)); 1540 SkScalar textSkewX = paint.getTextSkewX(); 1541 if (textSkewX != defaultPaint.getTextSkewX()) 1542 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1543 "{kTextSkewX, %g}, ", SkScalarToFloat(textSkewX)); 1544 SkScalar strokeWidth = paint.getStrokeWidth(); 1545 if (strokeWidth != defaultPaint.getStrokeWidth()) 1546 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1547 "{kStrokeWidth, %g}, ", SkScalarToFloat(strokeWidth)); 1548 SkScalar strokeMiter = paint.getStrokeMiter(); 1549 if (strokeMiter != defaultPaint.getStrokeMiter()) 1550 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1551 "{kStrokeMiter, %g}, ", SkScalarToFloat(strokeMiter)); 1552 SkDebugf("%s{0}};\n", pBuffer); 1553 bufferPtr = pBuffer; 1554 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1555 "PaintInts = paintInts%p = {", &paint); 1556 unsigned color = paint.getColor(); 1557 if (color != defaultPaint.getColor()) 1558 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1559 "{kColor, 0x%x}, ", color); 1560 unsigned flags = paint.getFlags(); 1561 if (flags != defaultPaint.getFlags()) 1562 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1563 "{kFlags, 0x%x}, ", flags); 1564 int align = paint.getTextAlign(); 1565 if (align != defaultPaint.getTextAlign()) 1566 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1567 "{kAlign, 0x%x}, ", align); 1568 int strokeCap = paint.getStrokeCap(); 1569 if (strokeCap != defaultPaint.getStrokeCap()) 1570 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1571 "{kStrokeCap, 0x%x}, ", strokeCap); 1572 int strokeJoin = paint.getStrokeJoin(); 1573 if (strokeJoin != defaultPaint.getStrokeJoin()) 1574 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1575 "{kAlign, 0x%x}, ", strokeJoin); 1576 int style = paint.getStyle(); 1577 if (style != defaultPaint.getStyle()) 1578 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1579 "{kStyle, 0x%x}, ", style); 1580 int textEncoding = paint.getTextEncoding(); 1581 if (textEncoding != defaultPaint.getTextEncoding()) 1582 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1583 "{kTextEncoding, 0x%x}, ", textEncoding); 1584 SkDebugf("%s{0}};\n", pBuffer); 1585 1586 SkDebugf("PaintData paint%p = {paintPtrs%p, paintScalars%p, paintInts%p};\n", 1587 &paint, &paint, &paint, &paint); 1588} 1589 1590void SkPicturePlayback::dumpPath(const SkPath& path) const { 1591 SkDebugf("path dump unimplemented\n"); 1592} 1593 1594void SkPicturePlayback::dumpPicture(const SkPicture& picture) const { 1595 SkDebugf("picture dump unimplemented\n"); 1596} 1597 1598void SkPicturePlayback::dumpRegion(const SkRegion& region) const { 1599 SkDebugf("region dump unimplemented\n"); 1600} 1601 1602int SkPicturePlayback::dumpDrawType(char* bufferPtr, char* buffer, DrawType drawType) { 1603 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer), 1604 "k%s, ", DrawTypeToString(drawType)); 1605} 1606 1607int SkPicturePlayback::dumpInt(char* bufferPtr, char* buffer, char* name) { 1608 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer), 1609 "%s:%d, ", name, getInt()); 1610} 1611 1612int SkPicturePlayback::dumpRect(char* bufferPtr, char* buffer, char* name) { 1613 const SkRect* rect = fReader.skipRect(); 1614 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer), 1615 "%s:{l:%g t:%g r:%g b:%g}, ", name, SkScalarToFloat(rect.fLeft), 1616 SkScalarToFloat(rect.fTop), 1617 SkScalarToFloat(rect.fRight), SkScalarToFloat(rect.fBottom)); 1618} 1619 1620int SkPicturePlayback::dumpPoint(char* bufferPtr, char* buffer, char* name) { 1621 SkPoint pt; 1622 getPoint(&pt); 1623 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer), 1624 "%s:{x:%g y:%g}, ", name, SkScalarToFloat(pt.fX), 1625 SkScalarToFloat(pt.fY)); 1626} 1627 1628void SkPicturePlayback::dumpPointArray(char** bufferPtrPtr, char* buffer, int count) { 1629 char* bufferPtr = *bufferPtrPtr; 1630 const SkPoint* pts = (const SkPoint*)fReadStream.getAtPos(); 1631 fReadStream.skip(sizeof(SkPoint) * count); 1632 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer), 1633 "count:%d {", count); 1634 for (int index = 0; index < count; index++) 1635 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer), 1636 "{x:%g y:%g}, ", SkScalarToFloat(pts[index].fX), 1637 SkScalarToFloat(pts[index].fY)); 1638 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer), 1639 "} "); 1640 *bufferPtrPtr = bufferPtr; 1641} 1642 1643int SkPicturePlayback::dumpPtr(char* bufferPtr, char* buffer, char* name, void* ptr) { 1644 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer), 1645 "%s:%p, ", name, ptr); 1646} 1647 1648int SkPicturePlayback::dumpRectPtr(char* bufferPtr, char* buffer, char* name) { 1649 char result; 1650 fReadStream.read(&result, sizeof(result)); 1651 if (result) 1652 return dumpRect(bufferPtr, buffer, name); 1653 else 1654 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer), 1655 "%s:NULL, ", name); 1656} 1657 1658int SkPicturePlayback::dumpScalar(char* bufferPtr, char* buffer, char* name) { 1659 return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer), 1660 "%s:%d, ", name, getScalar()); 1661} 1662 1663void SkPicturePlayback::dumpText(char** bufferPtrPtr, char* buffer) { 1664 char* bufferPtr = *bufferPtrPtr; 1665 int length = getInt(); 1666 bufferPtr += dumpDrawType(bufferPtr, buffer); 1667 fReadStream.skipToAlign4(); 1668 char* text = (char*) fReadStream.getAtPos(); 1669 fReadStream.skip(length); 1670 bufferPtr += dumpInt(bufferPtr, buffer, "length"); 1671 int limit = DUMP_BUFFER_SIZE - (bufferPtr - buffer) - 2; 1672 length >>= 1; 1673 if (limit > length) 1674 limit = length; 1675 if (limit > 0) { 1676 *bufferPtr++ = '"'; 1677 for (int index = 0; index < limit; index++) { 1678 *bufferPtr++ = *(unsigned short*) text; 1679 text += sizeof(unsigned short); 1680 } 1681 *bufferPtr++ = '"'; 1682 } 1683 *bufferPtrPtr = bufferPtr; 1684} 1685 1686#define DUMP_DRAWTYPE(drawType) \ 1687 bufferPtr += dumpDrawType(bufferPtr, buffer, drawType) 1688 1689#define DUMP_INT(name) \ 1690 bufferPtr += dumpInt(bufferPtr, buffer, #name) 1691 1692#define DUMP_RECT_PTR(name) \ 1693 bufferPtr += dumpRectPtr(bufferPtr, buffer, #name) 1694 1695#define DUMP_POINT(name) \ 1696 bufferPtr += dumpRect(bufferPtr, buffer, #name) 1697 1698#define DUMP_RECT(name) \ 1699 bufferPtr += dumpRect(bufferPtr, buffer, #name) 1700 1701#define DUMP_POINT_ARRAY(count) \ 1702 dumpPointArray(&bufferPtr, buffer, count) 1703 1704#define DUMP_PTR(name, ptr) \ 1705 bufferPtr += dumpPtr(bufferPtr, buffer, #name, (void*) ptr) 1706 1707#define DUMP_SCALAR(name) \ 1708 bufferPtr += dumpScalar(bufferPtr, buffer, #name) 1709 1710#define DUMP_TEXT() \ 1711 dumpText(&bufferPtr, buffer) 1712 1713void SkPicturePlayback::dumpStream() { 1714 SkDebugf("RecordStream stream = {\n"); 1715 DrawType drawType; 1716 TextContainer text; 1717 fReadStream.rewind(); 1718 char buffer[DUMP_BUFFER_SIZE], * bufferPtr; 1719 while (fReadStream.read(&drawType, sizeof(drawType))) { 1720 bufferPtr = buffer; 1721 DUMP_DRAWTYPE(drawType); 1722 switch (drawType) { 1723 case CLIP_PATH: { 1724 DUMP_PTR(SkPath, &getPath()); 1725 DUMP_INT(SkRegion::Op); 1726 DUMP_INT(offsetToRestore); 1727 } break; 1728 case CLIP_REGION: { 1729 DUMP_INT(SkRegion::Op); 1730 DUMP_INT(offsetToRestore); 1731 } break; 1732 case CLIP_RECT: { 1733 DUMP_RECT(rect); 1734 DUMP_INT(SkRegion::Op); 1735 DUMP_INT(offsetToRestore); 1736 } break; 1737 case CONCAT: 1738 break; 1739 case DRAW_BITMAP: { 1740 DUMP_PTR(SkPaint, getPaint()); 1741 DUMP_PTR(SkBitmap, &getBitmap()); 1742 DUMP_SCALAR(left); 1743 DUMP_SCALAR(top); 1744 } break; 1745 case DRAW_PAINT: 1746 DUMP_PTR(SkPaint, getPaint()); 1747 break; 1748 case DRAW_PATH: { 1749 DUMP_PTR(SkPaint, getPaint()); 1750 DUMP_PTR(SkPath, &getPath()); 1751 } break; 1752 case DRAW_PICTURE: { 1753 DUMP_PTR(SkPicture, &getPicture()); 1754 } break; 1755 case DRAW_POINTS: { 1756 DUMP_PTR(SkPaint, getPaint()); 1757 (void)getInt(); // PointMode 1758 size_t count = getInt(); 1759 fReadStream.skipToAlign4(); 1760 DUMP_POINT_ARRAY(count); 1761 } break; 1762 case DRAW_POS_TEXT: { 1763 DUMP_PTR(SkPaint, getPaint()); 1764 DUMP_TEXT(); 1765 size_t points = getInt(); 1766 fReadStream.skipToAlign4(); 1767 DUMP_POINT_ARRAY(points); 1768 } break; 1769 case DRAW_POS_TEXT_H: { 1770 DUMP_PTR(SkPaint, getPaint()); 1771 DUMP_TEXT(); 1772 size_t points = getInt(); 1773 fReadStream.skipToAlign4(); 1774 DUMP_SCALAR(top); 1775 DUMP_SCALAR(bottom); 1776 DUMP_SCALAR(constY); 1777 DUMP_POINT_ARRAY(points); 1778 } break; 1779 case DRAW_RECT: { 1780 DUMP_PTR(SkPaint, getPaint()); 1781 DUMP_RECT(rect); 1782 } break; 1783 case DRAW_SPRITE: { 1784 DUMP_PTR(SkPaint, getPaint()); 1785 DUMP_PTR(SkBitmap, &getBitmap()); 1786 DUMP_SCALAR(left); 1787 DUMP_SCALAR(top); 1788 } break; 1789 case DRAW_TEXT: { 1790 DUMP_PTR(SkPaint, getPaint()); 1791 DUMP_TEXT(); 1792 DUMP_SCALAR(x); 1793 DUMP_SCALAR(y); 1794 } break; 1795 case DRAW_TEXT_ON_PATH: { 1796 DUMP_PTR(SkPaint, getPaint()); 1797 DUMP_TEXT(); 1798 DUMP_PTR(SkPath, &getPath()); 1799 } break; 1800 case RESTORE: 1801 break; 1802 case ROTATE: 1803 DUMP_SCALAR(rotate); 1804 break; 1805 case SAVE: 1806 DUMP_INT(SkCanvas::SaveFlags); 1807 break; 1808 case SAVE_LAYER: { 1809 DUMP_RECT_PTR(layer); 1810 DUMP_PTR(SkPaint, getPaint()); 1811 DUMP_INT(SkCanvas::SaveFlags); 1812 } break; 1813 case SCALE: { 1814 DUMP_SCALAR(sx); 1815 DUMP_SCALAR(sy); 1816 } break; 1817 case SKEW: { 1818 DUMP_SCALAR(sx); 1819 DUMP_SCALAR(sy); 1820 } break; 1821 case TRANSLATE: { 1822 DUMP_SCALAR(dx); 1823 DUMP_SCALAR(dy); 1824 } break; 1825 default: 1826 SkASSERT(0); 1827 } 1828 SkDebugf("%s\n", buffer); 1829 } 1830} 1831 1832void SkPicturePlayback::dump() const { 1833 char pBuffer[DUMP_BUFFER_SIZE]; 1834 char* bufferPtr = pBuffer; 1835 int index; 1836 if (fBitmapCount > 0) 1837 SkDebugf("// bitmaps (%d)\n", fBitmapCount); 1838 for (index = 0; index < fBitmapCount; index++) { 1839 const SkBitmap& bitmap = fBitmaps[index]; 1840 dumpBitmap(bitmap); 1841 } 1842 if (fBitmapCount > 0) 1843 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1844 "Bitmaps bitmaps = {"); 1845 for (index = 0; index < fBitmapCount; index++) 1846 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1847 "bitmap%p, ", &fBitmaps[index]); 1848 if (fBitmapCount > 0) 1849 SkDebugf("%s0};\n", pBuffer); 1850 1851 1852 if (fPaintCount > 0) 1853 SkDebugf("// paints (%d)\n", fPaintCount); 1854 for (index = 0; index < fPaintCount; index++) { 1855 const SkPaint& paint = fPaints[index]; 1856 dumpPaint(paint); 1857 } 1858 bufferPtr = pBuffer; 1859 if (fPaintCount > 0) 1860 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1861 "Paints paints = {"); 1862 for (index = 0; index < fPaintCount; index++) 1863 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1864 "paint%p, ", &fPaints[index]); 1865 if (fPaintCount > 0) 1866 SkDebugf("%s0};\n", pBuffer); 1867 1868 for (index = 0; index < fPathCount; index++) { 1869 const SkPath& path = fPaths[index]; 1870 dumpPath(path); 1871 } 1872 bufferPtr = pBuffer; 1873 if (fPathCount > 0) 1874 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1875 "Paths paths = {"); 1876 for (index = 0; index < fPathCount; index++) 1877 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1878 "path%p, ", &fPaths[index]); 1879 if (fPathCount > 0) 1880 SkDebugf("%s0};\n", pBuffer); 1881 1882 for (index = 0; index < fPictureCount; index++) { 1883 dumpPicture(*fPictureRefs[index]); 1884 } 1885 bufferPtr = pBuffer; 1886 if (fPictureCount > 0) 1887 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1888 "Pictures pictures = {"); 1889 for (index = 0; index < fPictureCount; index++) 1890 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1891 "picture%p, ", fPictureRefs[index]); 1892 if (fPictureCount > 0) 1893 SkDebugf("%s0};\n", pBuffer); 1894 1895 const_cast<SkPicturePlayback*>(this)->dumpStream(); 1896} 1897 1898#endif 1899