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