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