1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/core/SkPicturePlayback.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1768 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2011 Google Inc. 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 +#include <new> 1.12 +#include "SkBBoxHierarchy.h" 1.13 +#include "SkOffsetTable.h" 1.14 +#include "SkPicturePlayback.h" 1.15 +#include "SkPictureRecord.h" 1.16 +#include "SkPictureStateTree.h" 1.17 +#include "SkReadBuffer.h" 1.18 +#include "SkTypeface.h" 1.19 +#include "SkTSort.h" 1.20 +#include "SkWriteBuffer.h" 1.21 + 1.22 +template <typename T> int SafeCount(const T* obj) { 1.23 + return obj ? obj->count() : 0; 1.24 +} 1.25 + 1.26 +/* Define this to spew out a debug statement whenever we skip the remainder of 1.27 + a save/restore block because a clip... command returned false (empty). 1.28 + */ 1.29 +#define SPEW_CLIP_SKIPPINGx 1.30 + 1.31 +SkPicturePlayback::SkPicturePlayback() { 1.32 + this->init(); 1.33 +} 1.34 + 1.35 +SkPicturePlayback::SkPicturePlayback(const SkPictureRecord& record, bool deepCopy) { 1.36 +#ifdef SK_DEBUG_SIZE 1.37 + size_t overallBytes, bitmapBytes, matricesBytes, 1.38 + paintBytes, pathBytes, pictureBytes, regionBytes; 1.39 + int bitmaps = record.bitmaps(&bitmapBytes); 1.40 + int matrices = record.matrices(&matricesBytes); 1.41 + int paints = record.paints(&paintBytes); 1.42 + int paths = record.paths(&pathBytes); 1.43 + int pictures = record.pictures(&pictureBytes); 1.44 + int regions = record.regions(®ionBytes); 1.45 + SkDebugf("picture record mem used %zd (stream %zd) ", record.size(), 1.46 + record.streamlen()); 1.47 + if (bitmaps != 0) 1.48 + SkDebugf("bitmaps size %zd (bitmaps:%d) ", bitmapBytes, bitmaps); 1.49 + if (matrices != 0) 1.50 + SkDebugf("matrices size %zd (matrices:%d) ", matricesBytes, matrices); 1.51 + if (paints != 0) 1.52 + SkDebugf("paints size %zd (paints:%d) ", paintBytes, paints); 1.53 + if (paths != 0) 1.54 + SkDebugf("paths size %zd (paths:%d) ", pathBytes, paths); 1.55 + if (pictures != 0) 1.56 + SkDebugf("pictures size %zd (pictures:%d) ", pictureBytes, pictures); 1.57 + if (regions != 0) 1.58 + SkDebugf("regions size %zd (regions:%d) ", regionBytes, regions); 1.59 + if (record.fPointWrites != 0) 1.60 + SkDebugf("points size %zd (points:%d) ", record.fPointBytes, record.fPointWrites); 1.61 + if (record.fRectWrites != 0) 1.62 + SkDebugf("rects size %zd (rects:%d) ", record.fRectBytes, record.fRectWrites); 1.63 + if (record.fTextWrites != 0) 1.64 + SkDebugf("text size %zd (text strings:%d) ", record.fTextBytes, record.fTextWrites); 1.65 + 1.66 + SkDebugf("\n"); 1.67 +#endif 1.68 +#ifdef SK_DEBUG_DUMP 1.69 + record.dumpMatrices(); 1.70 + record.dumpPaints(); 1.71 +#endif 1.72 + 1.73 + record.validate(record.writeStream().bytesWritten(), 0); 1.74 + const SkWriter32& writer = record.writeStream(); 1.75 + init(); 1.76 + SkASSERT(!fOpData); 1.77 + if (writer.bytesWritten() == 0) { 1.78 + fOpData = SkData::NewEmpty(); 1.79 + return; 1.80 + } 1.81 + fOpData = writer.snapshotAsData(); 1.82 + 1.83 + fBoundingHierarchy = record.fBoundingHierarchy; 1.84 + fStateTree = record.fStateTree; 1.85 + 1.86 + SkSafeRef(fBoundingHierarchy); 1.87 + SkSafeRef(fStateTree); 1.88 + 1.89 + if (NULL != fBoundingHierarchy) { 1.90 + fBoundingHierarchy->flushDeferredInserts(); 1.91 + } 1.92 + 1.93 + // copy over the refcnt dictionary to our reader 1.94 + record.fFlattenableHeap.setupPlaybacks(); 1.95 + 1.96 + fBitmaps = record.fBitmapHeap->extractBitmaps(); 1.97 + fPaints = record.fPaints.unflattenToArray(); 1.98 + 1.99 + fBitmapHeap.reset(SkSafeRef(record.fBitmapHeap)); 1.100 + fPathHeap.reset(SkSafeRef(record.fPathHeap)); 1.101 + 1.102 + fBitmapUseOffsets.reset(SkSafeRef(record.fBitmapUseOffsets.get())); 1.103 + 1.104 + // ensure that the paths bounds are pre-computed 1.105 + if (fPathHeap.get()) { 1.106 + for (int i = 0; i < fPathHeap->count(); i++) { 1.107 + (*fPathHeap)[i].updateBoundsCache(); 1.108 + } 1.109 + } 1.110 + 1.111 + const SkTDArray<SkPicture* >& pictures = record.getPictureRefs(); 1.112 + fPictureCount = pictures.count(); 1.113 + if (fPictureCount > 0) { 1.114 + fPictureRefs = SkNEW_ARRAY(SkPicture*, fPictureCount); 1.115 + for (int i = 0; i < fPictureCount; i++) { 1.116 + if (deepCopy) { 1.117 + fPictureRefs[i] = pictures[i]->clone(); 1.118 + } else { 1.119 + fPictureRefs[i] = pictures[i]; 1.120 + fPictureRefs[i]->ref(); 1.121 + } 1.122 + } 1.123 + } 1.124 + 1.125 +#ifdef SK_DEBUG_SIZE 1.126 + int overall = fPlayback->size(&overallBytes); 1.127 + bitmaps = fPlayback->bitmaps(&bitmapBytes); 1.128 + paints = fPlayback->paints(&paintBytes); 1.129 + paths = fPlayback->paths(&pathBytes); 1.130 + pictures = fPlayback->pictures(&pictureBytes); 1.131 + regions = fPlayback->regions(®ionBytes); 1.132 + SkDebugf("playback size %zd (objects:%d) ", overallBytes, overall); 1.133 + if (bitmaps != 0) 1.134 + SkDebugf("bitmaps size %zd (bitmaps:%d) ", bitmapBytes, bitmaps); 1.135 + if (paints != 0) 1.136 + SkDebugf("paints size %zd (paints:%d) ", paintBytes, paints); 1.137 + if (paths != 0) 1.138 + SkDebugf("paths size %zd (paths:%d) ", pathBytes, paths); 1.139 + if (pictures != 0) 1.140 + SkDebugf("pictures size %zd (pictures:%d) ", pictureBytes, pictures); 1.141 + if (regions != 0) 1.142 + SkDebugf("regions size %zd (regions:%d) ", regionBytes, regions); 1.143 + SkDebugf("\n"); 1.144 +#endif 1.145 +} 1.146 + 1.147 +static bool needs_deep_copy(const SkPaint& paint) { 1.148 + /* 1.149 + * These fields are known to be immutable, and so can be shallow-copied 1.150 + * 1.151 + * getTypeface() 1.152 + * getAnnotation() 1.153 + * paint.getColorFilter() 1.154 + * getXfermode() 1.155 + */ 1.156 + 1.157 + return paint.getPathEffect() || 1.158 + paint.getShader() || 1.159 + paint.getMaskFilter() || 1.160 + paint.getRasterizer() || 1.161 + paint.getLooper() || 1.162 + paint.getImageFilter(); 1.163 +} 1.164 + 1.165 +SkPicturePlayback::SkPicturePlayback(const SkPicturePlayback& src, SkPictCopyInfo* deepCopyInfo) { 1.166 + this->init(); 1.167 + 1.168 + fBitmapHeap.reset(SkSafeRef(src.fBitmapHeap.get())); 1.169 + fPathHeap.reset(SkSafeRef(src.fPathHeap.get())); 1.170 + 1.171 + fOpData = SkSafeRef(src.fOpData); 1.172 + 1.173 + fBoundingHierarchy = src.fBoundingHierarchy; 1.174 + fStateTree = src.fStateTree; 1.175 + 1.176 + SkSafeRef(fBoundingHierarchy); 1.177 + SkSafeRef(fStateTree); 1.178 + 1.179 + if (deepCopyInfo) { 1.180 + int paintCount = SafeCount(src.fPaints); 1.181 + 1.182 + if (src.fBitmaps) { 1.183 + fBitmaps = SkTRefArray<SkBitmap>::Create(src.fBitmaps->begin(), src.fBitmaps->count()); 1.184 + } 1.185 + 1.186 + if (!deepCopyInfo->initialized) { 1.187 + /* The alternative to doing this is to have a clone method on the paint and have it make 1.188 + * the deep copy of its internal structures as needed. The holdup to doing that is at 1.189 + * this point we would need to pass the SkBitmapHeap so that we don't unnecessarily 1.190 + * flatten the pixels in a bitmap shader. 1.191 + */ 1.192 + deepCopyInfo->paintData.setCount(paintCount); 1.193 + 1.194 + /* Use an SkBitmapHeap to avoid flattening bitmaps in shaders. If there already is one, 1.195 + * use it. If this SkPicturePlayback was created from a stream, fBitmapHeap will be 1.196 + * NULL, so create a new one. 1.197 + */ 1.198 + if (fBitmapHeap.get() == NULL) { 1.199 + // FIXME: Put this on the stack inside SkPicture::clone. Further, is it possible to 1.200 + // do the rest of this initialization in SkPicture::clone as well? 1.201 + SkBitmapHeap* heap = SkNEW(SkBitmapHeap); 1.202 + deepCopyInfo->controller.setBitmapStorage(heap); 1.203 + heap->unref(); 1.204 + } else { 1.205 + deepCopyInfo->controller.setBitmapStorage(fBitmapHeap); 1.206 + } 1.207 + 1.208 + SkDEBUGCODE(int heapSize = SafeCount(fBitmapHeap.get());) 1.209 + for (int i = 0; i < paintCount; i++) { 1.210 + if (needs_deep_copy(src.fPaints->at(i))) { 1.211 + deepCopyInfo->paintData[i] = 1.212 + SkFlatData::Create<SkPaint::FlatteningTraits>(&deepCopyInfo->controller, 1.213 + src.fPaints->at(i), 0); 1.214 + 1.215 + } else { 1.216 + // this is our sentinel, which we use in the unflatten loop 1.217 + deepCopyInfo->paintData[i] = NULL; 1.218 + } 1.219 + } 1.220 + SkASSERT(SafeCount(fBitmapHeap.get()) == heapSize); 1.221 + 1.222 + // needed to create typeface playback 1.223 + deepCopyInfo->controller.setupPlaybacks(); 1.224 + deepCopyInfo->initialized = true; 1.225 + } 1.226 + 1.227 + fPaints = SkTRefArray<SkPaint>::Create(paintCount); 1.228 + SkASSERT(deepCopyInfo->paintData.count() == paintCount); 1.229 + SkBitmapHeap* bmHeap = deepCopyInfo->controller.getBitmapHeap(); 1.230 + SkTypefacePlayback* tfPlayback = deepCopyInfo->controller.getTypefacePlayback(); 1.231 + for (int i = 0; i < paintCount; i++) { 1.232 + if (deepCopyInfo->paintData[i]) { 1.233 + deepCopyInfo->paintData[i]->unflatten<SkPaint::FlatteningTraits>( 1.234 + &fPaints->writableAt(i), bmHeap, tfPlayback); 1.235 + } else { 1.236 + // needs_deep_copy was false, so just need to assign 1.237 + fPaints->writableAt(i) = src.fPaints->at(i); 1.238 + } 1.239 + } 1.240 + 1.241 + } else { 1.242 + fBitmaps = SkSafeRef(src.fBitmaps); 1.243 + fPaints = SkSafeRef(src.fPaints); 1.244 + } 1.245 + 1.246 + fPictureCount = src.fPictureCount; 1.247 + fPictureRefs = SkNEW_ARRAY(SkPicture*, fPictureCount); 1.248 + for (int i = 0; i < fPictureCount; i++) { 1.249 + if (deepCopyInfo) { 1.250 + fPictureRefs[i] = src.fPictureRefs[i]->clone(); 1.251 + } else { 1.252 + fPictureRefs[i] = src.fPictureRefs[i]; 1.253 + fPictureRefs[i]->ref(); 1.254 + } 1.255 + } 1.256 +} 1.257 + 1.258 +void SkPicturePlayback::init() { 1.259 + fBitmaps = NULL; 1.260 + fPaints = NULL; 1.261 + fPictureRefs = NULL; 1.262 + fPictureCount = 0; 1.263 + fOpData = NULL; 1.264 + fFactoryPlayback = NULL; 1.265 + fBoundingHierarchy = NULL; 1.266 + fStateTree = NULL; 1.267 +} 1.268 + 1.269 +SkPicturePlayback::~SkPicturePlayback() { 1.270 + SkSafeUnref(fOpData); 1.271 + 1.272 + SkSafeUnref(fBitmaps); 1.273 + SkSafeUnref(fPaints); 1.274 + SkSafeUnref(fBoundingHierarchy); 1.275 + SkSafeUnref(fStateTree); 1.276 + 1.277 + for (int i = 0; i < fPictureCount; i++) { 1.278 + fPictureRefs[i]->unref(); 1.279 + } 1.280 + SkDELETE_ARRAY(fPictureRefs); 1.281 + 1.282 + SkDELETE(fFactoryPlayback); 1.283 +} 1.284 + 1.285 +void SkPicturePlayback::dumpSize() const { 1.286 + SkDebugf("--- picture size: ops=%d bitmaps=%d [%d] paints=%d [%d] paths=%d\n", 1.287 + fOpData->size(), 1.288 + SafeCount(fBitmaps), SafeCount(fBitmaps) * sizeof(SkBitmap), 1.289 + SafeCount(fPaints), SafeCount(fPaints) * sizeof(SkPaint), 1.290 + SafeCount(fPathHeap.get())); 1.291 +} 1.292 + 1.293 +bool SkPicturePlayback::containsBitmaps() const { 1.294 + if (fBitmaps && fBitmaps->count() > 0) { 1.295 + return true; 1.296 + } 1.297 + for (int i = 0; i < fPictureCount; ++i) { 1.298 + if (fPictureRefs[i]->willPlayBackBitmaps()) { 1.299 + return true; 1.300 + } 1.301 + } 1.302 + return false; 1.303 +} 1.304 + 1.305 +/////////////////////////////////////////////////////////////////////////////// 1.306 +/////////////////////////////////////////////////////////////////////////////// 1.307 + 1.308 +#include "SkStream.h" 1.309 + 1.310 +static void write_tag_size(SkWriteBuffer& buffer, uint32_t tag, uint32_t size) { 1.311 + buffer.writeUInt(tag); 1.312 + buffer.writeUInt(size); 1.313 +} 1.314 + 1.315 +static void write_tag_size(SkWStream* stream, uint32_t tag, uint32_t size) { 1.316 + stream->write32(tag); 1.317 + stream->write32(size); 1.318 +} 1.319 + 1.320 +static size_t compute_chunk_size(SkFlattenable::Factory* array, int count) { 1.321 + size_t size = 4; // for 'count' 1.322 + 1.323 + for (int i = 0; i < count; i++) { 1.324 + const char* name = SkFlattenable::FactoryToName(array[i]); 1.325 + if (NULL == name || 0 == *name) { 1.326 + size += SkWStream::SizeOfPackedUInt(0); 1.327 + } else { 1.328 + size_t len = strlen(name); 1.329 + size += SkWStream::SizeOfPackedUInt(len); 1.330 + size += len; 1.331 + } 1.332 + } 1.333 + 1.334 + return size; 1.335 +} 1.336 + 1.337 +static void write_factories(SkWStream* stream, const SkFactorySet& rec) { 1.338 + int count = rec.count(); 1.339 + 1.340 + SkAutoSTMalloc<16, SkFlattenable::Factory> storage(count); 1.341 + SkFlattenable::Factory* array = (SkFlattenable::Factory*)storage.get(); 1.342 + rec.copyToArray(array); 1.343 + 1.344 + size_t size = compute_chunk_size(array, count); 1.345 + 1.346 + // TODO: write_tag_size should really take a size_t 1.347 + write_tag_size(stream, SK_PICT_FACTORY_TAG, (uint32_t) size); 1.348 + SkDEBUGCODE(size_t start = stream->bytesWritten()); 1.349 + stream->write32(count); 1.350 + 1.351 + for (int i = 0; i < count; i++) { 1.352 + const char* name = SkFlattenable::FactoryToName(array[i]); 1.353 +// SkDebugf("---- write factories [%d] %p <%s>\n", i, array[i], name); 1.354 + if (NULL == name || 0 == *name) { 1.355 + stream->writePackedUInt(0); 1.356 + } else { 1.357 + uint32_t len = strlen(name); 1.358 + stream->writePackedUInt(len); 1.359 + stream->write(name, len); 1.360 + } 1.361 + } 1.362 + 1.363 + SkASSERT(size == (stream->bytesWritten() - start)); 1.364 +} 1.365 + 1.366 +static void write_typefaces(SkWStream* stream, const SkRefCntSet& rec) { 1.367 + int count = rec.count(); 1.368 + 1.369 + write_tag_size(stream, SK_PICT_TYPEFACE_TAG, count); 1.370 + 1.371 + SkAutoSTMalloc<16, SkTypeface*> storage(count); 1.372 + SkTypeface** array = (SkTypeface**)storage.get(); 1.373 + rec.copyToArray((SkRefCnt**)array); 1.374 + 1.375 + for (int i = 0; i < count; i++) { 1.376 + array[i]->serialize(stream); 1.377 + } 1.378 +} 1.379 + 1.380 +void SkPicturePlayback::flattenToBuffer(SkWriteBuffer& buffer) const { 1.381 + int i, n; 1.382 + 1.383 + if ((n = SafeCount(fBitmaps)) > 0) { 1.384 + write_tag_size(buffer, SK_PICT_BITMAP_BUFFER_TAG, n); 1.385 + for (i = 0; i < n; i++) { 1.386 + buffer.writeBitmap((*fBitmaps)[i]); 1.387 + } 1.388 + } 1.389 + 1.390 + if ((n = SafeCount(fPaints)) > 0) { 1.391 + write_tag_size(buffer, SK_PICT_PAINT_BUFFER_TAG, n); 1.392 + for (i = 0; i < n; i++) { 1.393 + buffer.writePaint((*fPaints)[i]); 1.394 + } 1.395 + } 1.396 + 1.397 + if ((n = SafeCount(fPathHeap.get())) > 0) { 1.398 + write_tag_size(buffer, SK_PICT_PATH_BUFFER_TAG, n); 1.399 + fPathHeap->flatten(buffer); 1.400 + } 1.401 +} 1.402 + 1.403 +void SkPicturePlayback::serialize(SkWStream* stream, 1.404 + SkPicture::EncodeBitmap encoder) const { 1.405 + write_tag_size(stream, SK_PICT_READER_TAG, fOpData->size()); 1.406 + stream->write(fOpData->bytes(), fOpData->size()); 1.407 + 1.408 + if (fPictureCount > 0) { 1.409 + write_tag_size(stream, SK_PICT_PICTURE_TAG, fPictureCount); 1.410 + for (int i = 0; i < fPictureCount; i++) { 1.411 + fPictureRefs[i]->serialize(stream, encoder); 1.412 + } 1.413 + } 1.414 + 1.415 + // Write some of our data into a writebuffer, and then serialize that 1.416 + // into our stream 1.417 + { 1.418 + SkRefCntSet typefaceSet; 1.419 + SkFactorySet factSet; 1.420 + 1.421 + SkWriteBuffer buffer(SkWriteBuffer::kCrossProcess_Flag); 1.422 + buffer.setTypefaceRecorder(&typefaceSet); 1.423 + buffer.setFactoryRecorder(&factSet); 1.424 + buffer.setBitmapEncoder(encoder); 1.425 + 1.426 + this->flattenToBuffer(buffer); 1.427 + 1.428 + // We have to write these two sets into the stream *before* we write 1.429 + // the buffer, since parsing that buffer will require that we already 1.430 + // have these sets available to use. 1.431 + write_factories(stream, factSet); 1.432 + write_typefaces(stream, typefaceSet); 1.433 + 1.434 + write_tag_size(stream, SK_PICT_BUFFER_SIZE_TAG, buffer.bytesWritten()); 1.435 + buffer.writeToStream(stream); 1.436 + } 1.437 + 1.438 + stream->write32(SK_PICT_EOF_TAG); 1.439 +} 1.440 + 1.441 +void SkPicturePlayback::flatten(SkWriteBuffer& buffer) const { 1.442 + write_tag_size(buffer, SK_PICT_READER_TAG, fOpData->size()); 1.443 + buffer.writeByteArray(fOpData->bytes(), fOpData->size()); 1.444 + 1.445 + if (fPictureCount > 0) { 1.446 + write_tag_size(buffer, SK_PICT_PICTURE_TAG, fPictureCount); 1.447 + for (int i = 0; i < fPictureCount; i++) { 1.448 + fPictureRefs[i]->flatten(buffer); 1.449 + } 1.450 + } 1.451 + 1.452 + // Write this picture playback's data into a writebuffer 1.453 + this->flattenToBuffer(buffer); 1.454 + buffer.write32(SK_PICT_EOF_TAG); 1.455 +} 1.456 + 1.457 +/////////////////////////////////////////////////////////////////////////////// 1.458 + 1.459 +/** 1.460 + * Return the corresponding SkReadBuffer flags, given a set of 1.461 + * SkPictInfo flags. 1.462 + */ 1.463 +static uint32_t pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags) { 1.464 + static const struct { 1.465 + uint32_t fSrc; 1.466 + uint32_t fDst; 1.467 + } gSD[] = { 1.468 + { SkPictInfo::kCrossProcess_Flag, SkReadBuffer::kCrossProcess_Flag }, 1.469 + { SkPictInfo::kScalarIsFloat_Flag, SkReadBuffer::kScalarIsFloat_Flag }, 1.470 + { SkPictInfo::kPtrIs64Bit_Flag, SkReadBuffer::kPtrIs64Bit_Flag }, 1.471 + }; 1.472 + 1.473 + uint32_t rbMask = 0; 1.474 + for (size_t i = 0; i < SK_ARRAY_COUNT(gSD); ++i) { 1.475 + if (pictInfoFlags & gSD[i].fSrc) { 1.476 + rbMask |= gSD[i].fDst; 1.477 + } 1.478 + } 1.479 + return rbMask; 1.480 +} 1.481 + 1.482 +bool SkPicturePlayback::parseStreamTag(SkStream* stream, const SkPictInfo& info, uint32_t tag, 1.483 + size_t size, SkPicture::InstallPixelRefProc proc) { 1.484 + /* 1.485 + * By the time we encounter BUFFER_SIZE_TAG, we need to have already seen 1.486 + * its dependents: FACTORY_TAG and TYPEFACE_TAG. These two are not required 1.487 + * but if they are present, they need to have been seen before the buffer. 1.488 + * 1.489 + * We assert that if/when we see either of these, that we have not yet seen 1.490 + * the buffer tag, because if we have, then its too-late to deal with the 1.491 + * factories or typefaces. 1.492 + */ 1.493 + SkDEBUGCODE(bool haveBuffer = false;) 1.494 + 1.495 + switch (tag) { 1.496 + case SK_PICT_READER_TAG: { 1.497 + SkAutoMalloc storage(size); 1.498 + if (stream->read(storage.get(), size) != size) { 1.499 + return false; 1.500 + } 1.501 + SkASSERT(NULL == fOpData); 1.502 + fOpData = SkData::NewFromMalloc(storage.detach(), size); 1.503 + } break; 1.504 + case SK_PICT_FACTORY_TAG: { 1.505 + SkASSERT(!haveBuffer); 1.506 + // Remove this code when v21 and below are no longer supported. At the 1.507 + // same time add a new 'count' variable and use it rather then reusing 'size'. 1.508 +#ifndef DISABLE_V21_COMPATIBILITY_CODE 1.509 + if (info.fVersion >= 22) { 1.510 + // in v22 this tag's size represents the size of the chunk in bytes 1.511 + // and the number of factory strings is written out separately 1.512 +#endif 1.513 + size = stream->readU32(); 1.514 +#ifndef DISABLE_V21_COMPATIBILITY_CODE 1.515 + } 1.516 +#endif 1.517 + fFactoryPlayback = SkNEW_ARGS(SkFactoryPlayback, (size)); 1.518 + for (size_t i = 0; i < size; i++) { 1.519 + SkString str; 1.520 + const size_t len = stream->readPackedUInt(); 1.521 + str.resize(len); 1.522 + if (stream->read(str.writable_str(), len) != len) { 1.523 + return false; 1.524 + } 1.525 + fFactoryPlayback->base()[i] = SkFlattenable::NameToFactory(str.c_str()); 1.526 + } 1.527 + } break; 1.528 + case SK_PICT_TYPEFACE_TAG: { 1.529 + SkASSERT(!haveBuffer); 1.530 + fTFPlayback.setCount(size); 1.531 + for (size_t i = 0; i < size; i++) { 1.532 + SkAutoTUnref<SkTypeface> tf(SkTypeface::Deserialize(stream)); 1.533 + if (!tf.get()) { // failed to deserialize 1.534 + // fTFPlayback asserts it never has a null, so we plop in 1.535 + // the default here. 1.536 + tf.reset(SkTypeface::RefDefault()); 1.537 + } 1.538 + fTFPlayback.set(i, tf); 1.539 + } 1.540 + } break; 1.541 + case SK_PICT_PICTURE_TAG: { 1.542 + fPictureCount = size; 1.543 + fPictureRefs = SkNEW_ARRAY(SkPicture*, fPictureCount); 1.544 + bool success = true; 1.545 + int i = 0; 1.546 + for ( ; i < fPictureCount; i++) { 1.547 + fPictureRefs[i] = SkPicture::CreateFromStream(stream, proc); 1.548 + if (NULL == fPictureRefs[i]) { 1.549 + success = false; 1.550 + break; 1.551 + } 1.552 + } 1.553 + if (!success) { 1.554 + // Delete all of the pictures that were already created (up to but excluding i): 1.555 + for (int j = 0; j < i; j++) { 1.556 + fPictureRefs[j]->unref(); 1.557 + } 1.558 + // Delete the array 1.559 + SkDELETE_ARRAY(fPictureRefs); 1.560 + fPictureCount = 0; 1.561 + return false; 1.562 + } 1.563 + } break; 1.564 + case SK_PICT_BUFFER_SIZE_TAG: { 1.565 + SkAutoMalloc storage(size); 1.566 + if (stream->read(storage.get(), size) != size) { 1.567 + return false; 1.568 + } 1.569 + 1.570 + SkReadBuffer buffer(storage.get(), size); 1.571 + buffer.setFlags(pictInfoFlagsToReadBufferFlags(info.fFlags)); 1.572 + 1.573 + fFactoryPlayback->setupBuffer(buffer); 1.574 + fTFPlayback.setupBuffer(buffer); 1.575 + buffer.setBitmapDecoder(proc); 1.576 + 1.577 + while (!buffer.eof()) { 1.578 + tag = buffer.readUInt(); 1.579 + size = buffer.readUInt(); 1.580 + if (!this->parseBufferTag(buffer, tag, size)) { 1.581 + return false; 1.582 + } 1.583 + } 1.584 + SkDEBUGCODE(haveBuffer = true;) 1.585 + } break; 1.586 + } 1.587 + return true; // success 1.588 +} 1.589 + 1.590 +bool SkPicturePlayback::parseBufferTag(SkReadBuffer& buffer, 1.591 + uint32_t tag, size_t size) { 1.592 + switch (tag) { 1.593 + case SK_PICT_BITMAP_BUFFER_TAG: { 1.594 + fBitmaps = SkTRefArray<SkBitmap>::Create(size); 1.595 + for (size_t i = 0; i < size; ++i) { 1.596 + SkBitmap* bm = &fBitmaps->writableAt(i); 1.597 + buffer.readBitmap(bm); 1.598 + bm->setImmutable(); 1.599 + } 1.600 + } break; 1.601 + case SK_PICT_PAINT_BUFFER_TAG: { 1.602 + fPaints = SkTRefArray<SkPaint>::Create(size); 1.603 + for (size_t i = 0; i < size; ++i) { 1.604 + buffer.readPaint(&fPaints->writableAt(i)); 1.605 + } 1.606 + } break; 1.607 + case SK_PICT_PATH_BUFFER_TAG: 1.608 + if (size > 0) { 1.609 + fPathHeap.reset(SkNEW_ARGS(SkPathHeap, (buffer))); 1.610 + } 1.611 + break; 1.612 + case SK_PICT_READER_TAG: { 1.613 + SkAutoMalloc storage(size); 1.614 + if (!buffer.readByteArray(storage.get(), size) || 1.615 + !buffer.validate(NULL == fOpData)) { 1.616 + return false; 1.617 + } 1.618 + SkASSERT(NULL == fOpData); 1.619 + fOpData = SkData::NewFromMalloc(storage.detach(), size); 1.620 + } break; 1.621 + case SK_PICT_PICTURE_TAG: { 1.622 + if (!buffer.validate((0 == fPictureCount) && (NULL == fPictureRefs))) { 1.623 + return false; 1.624 + } 1.625 + fPictureCount = size; 1.626 + fPictureRefs = SkNEW_ARRAY(SkPicture*, fPictureCount); 1.627 + bool success = true; 1.628 + int i = 0; 1.629 + for ( ; i < fPictureCount; i++) { 1.630 + fPictureRefs[i] = SkPicture::CreateFromBuffer(buffer); 1.631 + if (NULL == fPictureRefs[i]) { 1.632 + success = false; 1.633 + break; 1.634 + } 1.635 + } 1.636 + if (!success) { 1.637 + // Delete all of the pictures that were already created (up to but excluding i): 1.638 + for (int j = 0; j < i; j++) { 1.639 + fPictureRefs[j]->unref(); 1.640 + } 1.641 + // Delete the array 1.642 + SkDELETE_ARRAY(fPictureRefs); 1.643 + fPictureCount = 0; 1.644 + return false; 1.645 + } 1.646 + } break; 1.647 + default: 1.648 + // The tag was invalid. 1.649 + return false; 1.650 + } 1.651 + return true; // success 1.652 +} 1.653 + 1.654 +SkPicturePlayback* SkPicturePlayback::CreateFromStream(SkStream* stream, 1.655 + const SkPictInfo& info, 1.656 + SkPicture::InstallPixelRefProc proc) { 1.657 + SkAutoTDelete<SkPicturePlayback> playback(SkNEW(SkPicturePlayback)); 1.658 + 1.659 + if (!playback->parseStream(stream, info, proc)) { 1.660 + return NULL; 1.661 + } 1.662 + return playback.detach(); 1.663 +} 1.664 + 1.665 +SkPicturePlayback* SkPicturePlayback::CreateFromBuffer(SkReadBuffer& buffer) { 1.666 + SkAutoTDelete<SkPicturePlayback> playback(SkNEW(SkPicturePlayback)); 1.667 + 1.668 + if (!playback->parseBuffer(buffer)) { 1.669 + return NULL; 1.670 + } 1.671 + return playback.detach(); 1.672 +} 1.673 + 1.674 +bool SkPicturePlayback::parseStream(SkStream* stream, const SkPictInfo& info, 1.675 + SkPicture::InstallPixelRefProc proc) { 1.676 + for (;;) { 1.677 + uint32_t tag = stream->readU32(); 1.678 + if (SK_PICT_EOF_TAG == tag) { 1.679 + break; 1.680 + } 1.681 + 1.682 + uint32_t size = stream->readU32(); 1.683 + if (!this->parseStreamTag(stream, info, tag, size, proc)) { 1.684 + return false; // we're invalid 1.685 + } 1.686 + } 1.687 + return true; 1.688 +} 1.689 + 1.690 +bool SkPicturePlayback::parseBuffer(SkReadBuffer& buffer) { 1.691 + for (;;) { 1.692 + uint32_t tag = buffer.readUInt(); 1.693 + if (SK_PICT_EOF_TAG == tag) { 1.694 + break; 1.695 + } 1.696 + 1.697 + uint32_t size = buffer.readUInt(); 1.698 + if (!this->parseBufferTag(buffer, tag, size)) { 1.699 + return false; // we're invalid 1.700 + } 1.701 + } 1.702 + return true; 1.703 +} 1.704 + 1.705 +/////////////////////////////////////////////////////////////////////////////// 1.706 +/////////////////////////////////////////////////////////////////////////////// 1.707 + 1.708 +#ifdef SPEW_CLIP_SKIPPING 1.709 +struct SkipClipRec { 1.710 + int fCount; 1.711 + size_t fSize; 1.712 + 1.713 + SkipClipRec() { 1.714 + fCount = 0; 1.715 + fSize = 0; 1.716 + } 1.717 + 1.718 + void recordSkip(size_t bytes) { 1.719 + fCount += 1; 1.720 + fSize += bytes; 1.721 + } 1.722 +}; 1.723 +#endif 1.724 + 1.725 +#ifdef SK_DEVELOPER 1.726 +bool SkPicturePlayback::preDraw(int opIndex, int type) { 1.727 + return false; 1.728 +} 1.729 + 1.730 +void SkPicturePlayback::postDraw(int opIndex) { 1.731 +} 1.732 +#endif 1.733 + 1.734 +/* 1.735 + * Read the next op code and chunk size from 'reader'. The returned size 1.736 + * is the entire size of the chunk (including the opcode). Thus, the 1.737 + * offset just prior to calling read_op_and_size + 'size' is the offset 1.738 + * to the next chunk's op code. This also means that the size of a chunk 1.739 + * with no arguments (just an opcode) will be 4. 1.740 + */ 1.741 +static DrawType read_op_and_size(SkReader32* reader, uint32_t* size) { 1.742 + uint32_t temp = reader->readInt(); 1.743 + uint32_t op; 1.744 + if (((uint8_t) temp) == temp) { 1.745 + // old skp file - no size information 1.746 + op = temp; 1.747 + *size = 0; 1.748 + } else { 1.749 + UNPACK_8_24(temp, op, *size); 1.750 + if (MASK_24 == *size) { 1.751 + *size = reader->readInt(); 1.752 + } 1.753 + } 1.754 + return (DrawType) op; 1.755 +} 1.756 + 1.757 +// The activeOps parameter is actually "const SkTDArray<SkPictureStateTree::Draw*>&". 1.758 +// It represents the operations about to be drawn, as generated by some spatial 1.759 +// subdivision helper class. It should already be in 'fOffset' sorted order. 1.760 +void SkPicturePlayback::preLoadBitmaps(const SkTDArray<void*>& activeOps) { 1.761 + if (0 == activeOps.count() || NULL == fBitmapUseOffsets) { 1.762 + return; 1.763 + } 1.764 + 1.765 + SkTDArray<int> active; 1.766 + 1.767 + SkAutoTDeleteArray<bool> needToCheck(new bool[fBitmapUseOffsets->numIDs()]); 1.768 + for (int i = 0; i < fBitmapUseOffsets->numIDs(); ++i) { 1.769 + needToCheck.get()[i] = true; 1.770 + } 1.771 + 1.772 + uint32_t max = ((SkPictureStateTree::Draw*)activeOps[activeOps.count()-1])->fOffset; 1.773 + 1.774 + for (int i = 0; i < activeOps.count(); ++i) { 1.775 + SkPictureStateTree::Draw* draw = (SkPictureStateTree::Draw*) activeOps[i]; 1.776 + 1.777 + for (int j = 0; j < fBitmapUseOffsets->numIDs(); ++j) { 1.778 + if (!needToCheck.get()[j]) { 1.779 + continue; 1.780 + } 1.781 + 1.782 + if (!fBitmapUseOffsets->overlap(j, draw->fOffset, max)) { 1.783 + needToCheck.get()[j] = false; 1.784 + continue; 1.785 + } 1.786 + 1.787 + if (!fBitmapUseOffsets->includes(j, draw->fOffset)) { 1.788 + continue; 1.789 + } 1.790 + 1.791 + *active.append() = j; 1.792 + needToCheck.get()[j] = false; 1.793 + } 1.794 + } 1.795 + 1.796 + for (int i = 0; i < active.count(); ++i) { 1.797 + SkDebugf("preload texture %d\n", active[i]); 1.798 + } 1.799 +} 1.800 + 1.801 +void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback) { 1.802 +#ifdef ENABLE_TIME_DRAW 1.803 + SkAutoTime at("SkPicture::draw", 50); 1.804 +#endif 1.805 + 1.806 +#ifdef SPEW_CLIP_SKIPPING 1.807 + SkipClipRec skipRect, skipRRect, skipRegion, skipPath, skipCull; 1.808 + int opCount = 0; 1.809 +#endif 1.810 + 1.811 +#ifdef SK_BUILD_FOR_ANDROID 1.812 + SkAutoMutexAcquire autoMutex(fDrawMutex); 1.813 +#endif 1.814 + 1.815 + // kDrawComplete will be the signal that we have reached the end of 1.816 + // the command stream 1.817 + static const uint32_t kDrawComplete = SK_MaxU32; 1.818 + 1.819 + SkReader32 reader(fOpData->bytes(), fOpData->size()); 1.820 + TextContainer text; 1.821 + SkTDArray<void*> activeOps; 1.822 + 1.823 + if (NULL != fStateTree && NULL != fBoundingHierarchy) { 1.824 + SkRect clipBounds; 1.825 + if (canvas.getClipBounds(&clipBounds)) { 1.826 + SkIRect query; 1.827 + clipBounds.roundOut(&query); 1.828 + fBoundingHierarchy->search(query, &activeOps); 1.829 + if (activeOps.count() == 0) { 1.830 + return; 1.831 + } 1.832 + SkTQSort<SkPictureStateTree::Draw>( 1.833 + reinterpret_cast<SkPictureStateTree::Draw**>(activeOps.begin()), 1.834 + reinterpret_cast<SkPictureStateTree::Draw**>(activeOps.end()-1)); 1.835 + } 1.836 + } 1.837 + 1.838 + SkPictureStateTree::Iterator it = (NULL == fStateTree) ? 1.839 + SkPictureStateTree::Iterator() : 1.840 + fStateTree->getIterator(activeOps, &canvas); 1.841 + 1.842 + if (it.isValid()) { 1.843 + uint32_t skipTo = it.draw(); 1.844 + if (kDrawComplete == skipTo) { 1.845 + return; 1.846 + } 1.847 + reader.setOffset(skipTo); 1.848 + } 1.849 + 1.850 + this->preLoadBitmaps(activeOps); 1.851 + 1.852 + // Record this, so we can concat w/ it if we encounter a setMatrix() 1.853 + SkMatrix initialMatrix = canvas.getTotalMatrix(); 1.854 + int originalSaveCount = canvas.getSaveCount(); 1.855 + 1.856 +#ifdef SK_BUILD_FOR_ANDROID 1.857 + fAbortCurrentPlayback = false; 1.858 +#endif 1.859 + 1.860 +#ifdef SK_DEVELOPER 1.861 + int opIndex = -1; 1.862 +#endif 1.863 + 1.864 + while (!reader.eof()) { 1.865 + if (callback && callback->abortDrawing()) { 1.866 + canvas.restoreToCount(originalSaveCount); 1.867 + return; 1.868 + } 1.869 +#ifdef SK_BUILD_FOR_ANDROID 1.870 + if (fAbortCurrentPlayback) { 1.871 + return; 1.872 + } 1.873 +#endif 1.874 + 1.875 +#ifdef SPEW_CLIP_SKIPPING 1.876 + opCount++; 1.877 +#endif 1.878 + 1.879 + size_t curOffset = reader.offset(); 1.880 + uint32_t size; 1.881 + DrawType op = read_op_and_size(&reader, &size); 1.882 + size_t skipTo = 0; 1.883 + if (NOOP == op) { 1.884 + // NOOPs are to be ignored - do not propagate them any further 1.885 + skipTo = curOffset + size; 1.886 +#ifdef SK_DEVELOPER 1.887 + } else { 1.888 + opIndex++; 1.889 + if (this->preDraw(opIndex, op)) { 1.890 + skipTo = curOffset + size; 1.891 + } 1.892 +#endif 1.893 + } 1.894 + 1.895 + if (0 != skipTo) { 1.896 + if (it.isValid()) { 1.897 + // If using a bounding box hierarchy, advance the state tree 1.898 + // iterator until at or after skipTo 1.899 + uint32_t adjustedSkipTo; 1.900 + do { 1.901 + adjustedSkipTo = it.draw(); 1.902 + } while (adjustedSkipTo < skipTo); 1.903 + skipTo = adjustedSkipTo; 1.904 + } 1.905 + if (kDrawComplete == skipTo) { 1.906 + break; 1.907 + } 1.908 + reader.setOffset(skipTo); 1.909 + continue; 1.910 + } 1.911 + 1.912 + switch (op) { 1.913 + case CLIP_PATH: { 1.914 + const SkPath& path = getPath(reader); 1.915 + uint32_t packed = reader.readInt(); 1.916 + SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed); 1.917 + bool doAA = ClipParams_unpackDoAA(packed); 1.918 + size_t offsetToRestore = reader.readInt(); 1.919 + SkASSERT(!offsetToRestore || \ 1.920 + offsetToRestore >= reader.offset()); 1.921 + canvas.clipPath(path, regionOp, doAA); 1.922 + if (canvas.isClipEmpty() && offsetToRestore) { 1.923 +#ifdef SPEW_CLIP_SKIPPING 1.924 + skipPath.recordSkip(offsetToRestore - reader.offset()); 1.925 +#endif 1.926 + reader.setOffset(offsetToRestore); 1.927 + } 1.928 + } break; 1.929 + case CLIP_REGION: { 1.930 + SkRegion region; 1.931 + this->getRegion(reader, ®ion); 1.932 + uint32_t packed = reader.readInt(); 1.933 + SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed); 1.934 + size_t offsetToRestore = reader.readInt(); 1.935 + SkASSERT(!offsetToRestore || \ 1.936 + offsetToRestore >= reader.offset()); 1.937 + canvas.clipRegion(region, regionOp); 1.938 + if (canvas.isClipEmpty() && offsetToRestore) { 1.939 +#ifdef SPEW_CLIP_SKIPPING 1.940 + skipRegion.recordSkip(offsetToRestore - reader.offset()); 1.941 +#endif 1.942 + reader.setOffset(offsetToRestore); 1.943 + } 1.944 + } break; 1.945 + case CLIP_RECT: { 1.946 + const SkRect& rect = reader.skipT<SkRect>(); 1.947 + uint32_t packed = reader.readInt(); 1.948 + SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed); 1.949 + bool doAA = ClipParams_unpackDoAA(packed); 1.950 + size_t offsetToRestore = reader.readInt(); 1.951 + SkASSERT(!offsetToRestore || \ 1.952 + offsetToRestore >= reader.offset()); 1.953 + canvas.clipRect(rect, regionOp, doAA); 1.954 + if (canvas.isClipEmpty() && offsetToRestore) { 1.955 +#ifdef SPEW_CLIP_SKIPPING 1.956 + skipRect.recordSkip(offsetToRestore - reader.offset()); 1.957 +#endif 1.958 + reader.setOffset(offsetToRestore); 1.959 + } 1.960 + } break; 1.961 + case CLIP_RRECT: { 1.962 + SkRRect rrect; 1.963 + reader.readRRect(&rrect); 1.964 + uint32_t packed = reader.readInt(); 1.965 + SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed); 1.966 + bool doAA = ClipParams_unpackDoAA(packed); 1.967 + size_t offsetToRestore = reader.readInt(); 1.968 + SkASSERT(!offsetToRestore || \ 1.969 + offsetToRestore >= reader.offset()); 1.970 + canvas.clipRRect(rrect, regionOp, doAA); 1.971 + if (canvas.isClipEmpty() && offsetToRestore) { 1.972 +#ifdef SPEW_CLIP_SKIPPING 1.973 + skipRRect.recordSkip(offsetToRestore - reader.offset()); 1.974 +#endif 1.975 + reader.setOffset(offsetToRestore); 1.976 + } 1.977 + } break; 1.978 + case PUSH_CULL: { 1.979 + const SkRect& cullRect = reader.skipT<SkRect>(); 1.980 + size_t offsetToRestore = reader.readInt(); 1.981 + if (offsetToRestore && canvas.quickReject(cullRect)) { 1.982 +#ifdef SPEW_CLIP_SKIPPING 1.983 + skipCull.recordSkip(offsetToRestore - reader.offset()); 1.984 +#endif 1.985 + reader.setOffset(offsetToRestore); 1.986 + } else { 1.987 + canvas.pushCull(cullRect); 1.988 + } 1.989 + } break; 1.990 + case POP_CULL: 1.991 + canvas.popCull(); 1.992 + break; 1.993 + case CONCAT: { 1.994 + SkMatrix matrix; 1.995 + this->getMatrix(reader, &matrix); 1.996 + canvas.concat(matrix); 1.997 + break; 1.998 + } 1.999 + case DRAW_BITMAP: { 1.1000 + const SkPaint* paint = this->getPaint(reader); 1.1001 + const SkBitmap& bitmap = this->getBitmap(reader); 1.1002 + const SkPoint& loc = reader.skipT<SkPoint>(); 1.1003 + canvas.drawBitmap(bitmap, loc.fX, loc.fY, paint); 1.1004 + } break; 1.1005 + case DRAW_BITMAP_RECT_TO_RECT: { 1.1006 + const SkPaint* paint = this->getPaint(reader); 1.1007 + const SkBitmap& bitmap = this->getBitmap(reader); 1.1008 + const SkRect* src = this->getRectPtr(reader); // may be null 1.1009 + const SkRect& dst = reader.skipT<SkRect>(); // required 1.1010 + SkCanvas::DrawBitmapRectFlags flags; 1.1011 + flags = (SkCanvas::DrawBitmapRectFlags) reader.readInt(); 1.1012 + canvas.drawBitmapRectToRect(bitmap, src, dst, paint, flags); 1.1013 + } break; 1.1014 + case DRAW_BITMAP_MATRIX: { 1.1015 + const SkPaint* paint = this->getPaint(reader); 1.1016 + const SkBitmap& bitmap = this->getBitmap(reader); 1.1017 + SkMatrix matrix; 1.1018 + this->getMatrix(reader, &matrix); 1.1019 + canvas.drawBitmapMatrix(bitmap, matrix, paint); 1.1020 + } break; 1.1021 + case DRAW_BITMAP_NINE: { 1.1022 + const SkPaint* paint = this->getPaint(reader); 1.1023 + const SkBitmap& bitmap = this->getBitmap(reader); 1.1024 + const SkIRect& src = reader.skipT<SkIRect>(); 1.1025 + const SkRect& dst = reader.skipT<SkRect>(); 1.1026 + canvas.drawBitmapNine(bitmap, src, dst, paint); 1.1027 + } break; 1.1028 + case DRAW_CLEAR: 1.1029 + canvas.clear(reader.readInt()); 1.1030 + break; 1.1031 + case DRAW_DATA: { 1.1032 + size_t length = reader.readInt(); 1.1033 + canvas.drawData(reader.skip(length), length); 1.1034 + // skip handles padding the read out to a multiple of 4 1.1035 + } break; 1.1036 + case DRAW_DRRECT: { 1.1037 + const SkPaint& paint = *this->getPaint(reader); 1.1038 + SkRRect outer, inner; 1.1039 + reader.readRRect(&outer); 1.1040 + reader.readRRect(&inner); 1.1041 + canvas.drawDRRect(outer, inner, paint); 1.1042 + } break; 1.1043 + case BEGIN_COMMENT_GROUP: { 1.1044 + const char* desc = reader.readString(); 1.1045 + canvas.beginCommentGroup(desc); 1.1046 + } break; 1.1047 + case COMMENT: { 1.1048 + const char* kywd = reader.readString(); 1.1049 + const char* value = reader.readString(); 1.1050 + canvas.addComment(kywd, value); 1.1051 + } break; 1.1052 + case END_COMMENT_GROUP: { 1.1053 + canvas.endCommentGroup(); 1.1054 + } break; 1.1055 + case DRAW_OVAL: { 1.1056 + const SkPaint& paint = *this->getPaint(reader); 1.1057 + canvas.drawOval(reader.skipT<SkRect>(), paint); 1.1058 + } break; 1.1059 + case DRAW_PAINT: 1.1060 + canvas.drawPaint(*this->getPaint(reader)); 1.1061 + break; 1.1062 + case DRAW_PATH: { 1.1063 + const SkPaint& paint = *this->getPaint(reader); 1.1064 + canvas.drawPath(getPath(reader), paint); 1.1065 + } break; 1.1066 + case DRAW_PICTURE: 1.1067 + canvas.drawPicture(this->getPicture(reader)); 1.1068 + break; 1.1069 + case DRAW_POINTS: { 1.1070 + const SkPaint& paint = *this->getPaint(reader); 1.1071 + SkCanvas::PointMode mode = (SkCanvas::PointMode)reader.readInt(); 1.1072 + size_t count = reader.readInt(); 1.1073 + const SkPoint* pts = (const SkPoint*)reader.skip(sizeof(SkPoint) * count); 1.1074 + canvas.drawPoints(mode, count, pts, paint); 1.1075 + } break; 1.1076 + case DRAW_POS_TEXT: { 1.1077 + const SkPaint& paint = *this->getPaint(reader); 1.1078 + getText(reader, &text); 1.1079 + size_t points = reader.readInt(); 1.1080 + const SkPoint* pos = (const SkPoint*)reader.skip(points * sizeof(SkPoint)); 1.1081 + canvas.drawPosText(text.text(), text.length(), pos, paint); 1.1082 + } break; 1.1083 + case DRAW_POS_TEXT_TOP_BOTTOM: { 1.1084 + const SkPaint& paint = *this->getPaint(reader); 1.1085 + getText(reader, &text); 1.1086 + size_t points = reader.readInt(); 1.1087 + const SkPoint* pos = (const SkPoint*)reader.skip(points * sizeof(SkPoint)); 1.1088 + const SkScalar top = reader.readScalar(); 1.1089 + const SkScalar bottom = reader.readScalar(); 1.1090 + if (!canvas.quickRejectY(top, bottom)) { 1.1091 + canvas.drawPosText(text.text(), text.length(), pos, paint); 1.1092 + } 1.1093 + } break; 1.1094 + case DRAW_POS_TEXT_H: { 1.1095 + const SkPaint& paint = *this->getPaint(reader); 1.1096 + getText(reader, &text); 1.1097 + size_t xCount = reader.readInt(); 1.1098 + const SkScalar constY = reader.readScalar(); 1.1099 + const SkScalar* xpos = (const SkScalar*)reader.skip(xCount * sizeof(SkScalar)); 1.1100 + canvas.drawPosTextH(text.text(), text.length(), xpos, constY, 1.1101 + paint); 1.1102 + } break; 1.1103 + case DRAW_POS_TEXT_H_TOP_BOTTOM: { 1.1104 + const SkPaint& paint = *this->getPaint(reader); 1.1105 + getText(reader, &text); 1.1106 + size_t xCount = reader.readInt(); 1.1107 + const SkScalar* xpos = (const SkScalar*)reader.skip((3 + xCount) * sizeof(SkScalar)); 1.1108 + const SkScalar top = *xpos++; 1.1109 + const SkScalar bottom = *xpos++; 1.1110 + const SkScalar constY = *xpos++; 1.1111 + if (!canvas.quickRejectY(top, bottom)) { 1.1112 + canvas.drawPosTextH(text.text(), text.length(), xpos, 1.1113 + constY, paint); 1.1114 + } 1.1115 + } break; 1.1116 + case DRAW_RECT: { 1.1117 + const SkPaint& paint = *this->getPaint(reader); 1.1118 + canvas.drawRect(reader.skipT<SkRect>(), paint); 1.1119 + } break; 1.1120 + case DRAW_RRECT: { 1.1121 + const SkPaint& paint = *this->getPaint(reader); 1.1122 + SkRRect rrect; 1.1123 + reader.readRRect(&rrect); 1.1124 + canvas.drawRRect(rrect, paint); 1.1125 + } break; 1.1126 + case DRAW_SPRITE: { 1.1127 + const SkPaint* paint = this->getPaint(reader); 1.1128 + const SkBitmap& bitmap = this->getBitmap(reader); 1.1129 + int left = reader.readInt(); 1.1130 + int top = reader.readInt(); 1.1131 + canvas.drawSprite(bitmap, left, top, paint); 1.1132 + } break; 1.1133 + case DRAW_TEXT: { 1.1134 + const SkPaint& paint = *this->getPaint(reader); 1.1135 + this->getText(reader, &text); 1.1136 + SkScalar x = reader.readScalar(); 1.1137 + SkScalar y = reader.readScalar(); 1.1138 + canvas.drawText(text.text(), text.length(), x, y, paint); 1.1139 + } break; 1.1140 + case DRAW_TEXT_TOP_BOTTOM: { 1.1141 + const SkPaint& paint = *this->getPaint(reader); 1.1142 + this->getText(reader, &text); 1.1143 + const SkScalar* ptr = (const SkScalar*)reader.skip(4 * sizeof(SkScalar)); 1.1144 + // ptr[0] == x 1.1145 + // ptr[1] == y 1.1146 + // ptr[2] == top 1.1147 + // ptr[3] == bottom 1.1148 + if (!canvas.quickRejectY(ptr[2], ptr[3])) { 1.1149 + canvas.drawText(text.text(), text.length(), ptr[0], ptr[1], 1.1150 + paint); 1.1151 + } 1.1152 + } break; 1.1153 + case DRAW_TEXT_ON_PATH: { 1.1154 + const SkPaint& paint = *this->getPaint(reader); 1.1155 + getText(reader, &text); 1.1156 + const SkPath& path = this->getPath(reader); 1.1157 + SkMatrix matrix; 1.1158 + this->getMatrix(reader, &matrix); 1.1159 + canvas.drawTextOnPath(text.text(), text.length(), path, &matrix, paint); 1.1160 + } break; 1.1161 + case DRAW_VERTICES: { 1.1162 + SkAutoTUnref<SkXfermode> xfer; 1.1163 + const SkPaint& paint = *this->getPaint(reader); 1.1164 + DrawVertexFlags flags = (DrawVertexFlags)reader.readInt(); 1.1165 + SkCanvas::VertexMode vmode = (SkCanvas::VertexMode)reader.readInt(); 1.1166 + int vCount = reader.readInt(); 1.1167 + const SkPoint* verts = (const SkPoint*)reader.skip( 1.1168 + vCount * sizeof(SkPoint)); 1.1169 + const SkPoint* texs = NULL; 1.1170 + const SkColor* colors = NULL; 1.1171 + const uint16_t* indices = NULL; 1.1172 + int iCount = 0; 1.1173 + if (flags & DRAW_VERTICES_HAS_TEXS) { 1.1174 + texs = (const SkPoint*)reader.skip( 1.1175 + vCount * sizeof(SkPoint)); 1.1176 + } 1.1177 + if (flags & DRAW_VERTICES_HAS_COLORS) { 1.1178 + colors = (const SkColor*)reader.skip( 1.1179 + vCount * sizeof(SkColor)); 1.1180 + } 1.1181 + if (flags & DRAW_VERTICES_HAS_INDICES) { 1.1182 + iCount = reader.readInt(); 1.1183 + indices = (const uint16_t*)reader.skip( 1.1184 + iCount * sizeof(uint16_t)); 1.1185 + } 1.1186 + if (flags & DRAW_VERTICES_HAS_XFER) { 1.1187 + int mode = reader.readInt(); 1.1188 + if (mode < 0 || mode > SkXfermode::kLastMode) { 1.1189 + mode = SkXfermode::kModulate_Mode; 1.1190 + } 1.1191 + xfer.reset(SkXfermode::Create((SkXfermode::Mode)mode)); 1.1192 + } 1.1193 + canvas.drawVertices(vmode, vCount, verts, texs, colors, xfer, 1.1194 + indices, iCount, paint); 1.1195 + } break; 1.1196 + case RESTORE: 1.1197 + canvas.restore(); 1.1198 + break; 1.1199 + case ROTATE: 1.1200 + canvas.rotate(reader.readScalar()); 1.1201 + break; 1.1202 + case SAVE: 1.1203 + canvas.save((SkCanvas::SaveFlags) reader.readInt()); 1.1204 + break; 1.1205 + case SAVE_LAYER: { 1.1206 + const SkRect* boundsPtr = this->getRectPtr(reader); 1.1207 + const SkPaint* paint = this->getPaint(reader); 1.1208 + canvas.saveLayer(boundsPtr, paint, (SkCanvas::SaveFlags) reader.readInt()); 1.1209 + } break; 1.1210 + case SCALE: { 1.1211 + SkScalar sx = reader.readScalar(); 1.1212 + SkScalar sy = reader.readScalar(); 1.1213 + canvas.scale(sx, sy); 1.1214 + } break; 1.1215 + case SET_MATRIX: { 1.1216 + SkMatrix matrix; 1.1217 + this->getMatrix(reader, &matrix); 1.1218 + matrix.postConcat(initialMatrix); 1.1219 + canvas.setMatrix(matrix); 1.1220 + } break; 1.1221 + case SKEW: { 1.1222 + SkScalar sx = reader.readScalar(); 1.1223 + SkScalar sy = reader.readScalar(); 1.1224 + canvas.skew(sx, sy); 1.1225 + } break; 1.1226 + case TRANSLATE: { 1.1227 + SkScalar dx = reader.readScalar(); 1.1228 + SkScalar dy = reader.readScalar(); 1.1229 + canvas.translate(dx, dy); 1.1230 + } break; 1.1231 + default: 1.1232 + SkASSERT(0); 1.1233 + } 1.1234 + 1.1235 +#ifdef SK_DEVELOPER 1.1236 + this->postDraw(opIndex); 1.1237 +#endif 1.1238 + 1.1239 + if (it.isValid()) { 1.1240 + uint32_t skipTo = it.draw(); 1.1241 + if (kDrawComplete == skipTo) { 1.1242 + break; 1.1243 + } 1.1244 + reader.setOffset(skipTo); 1.1245 + } 1.1246 + } 1.1247 + 1.1248 +#ifdef SPEW_CLIP_SKIPPING 1.1249 + { 1.1250 + size_t size = skipRect.fSize + skipRRect.fSize + skipPath.fSize + skipRegion.fSize + 1.1251 + skipCull.fSize; 1.1252 + SkDebugf("--- Clip skips %d%% rect:%d rrect:%d path:%d rgn:%d cull:%d\n", 1.1253 + size * 100 / reader.offset(), skipRect.fCount, skipRRect.fCount, 1.1254 + skipPath.fCount, skipRegion.fCount, skipCull.fCount); 1.1255 + SkDebugf("--- Total ops: %d\n", opCount); 1.1256 + } 1.1257 +#endif 1.1258 +// this->dumpSize(); 1.1259 +} 1.1260 + 1.1261 +/////////////////////////////////////////////////////////////////////////////// 1.1262 + 1.1263 +#ifdef SK_DEBUG_SIZE 1.1264 +int SkPicturePlayback::size(size_t* sizePtr) { 1.1265 + int objects = bitmaps(sizePtr); 1.1266 + objects += paints(sizePtr); 1.1267 + objects += paths(sizePtr); 1.1268 + objects += pictures(sizePtr); 1.1269 + objects += regions(sizePtr); 1.1270 + *sizePtr = fOpData.size(); 1.1271 + return objects; 1.1272 +} 1.1273 + 1.1274 +int SkPicturePlayback::bitmaps(size_t* size) { 1.1275 + size_t result = 0; 1.1276 + for (int index = 0; index < fBitmapCount; index++) { 1.1277 + // const SkBitmap& bitmap = fBitmaps[index]; 1.1278 + result += sizeof(SkBitmap); // bitmap->size(); 1.1279 + } 1.1280 + *size = result; 1.1281 + return fBitmapCount; 1.1282 +} 1.1283 + 1.1284 +int SkPicturePlayback::paints(size_t* size) { 1.1285 + size_t result = 0; 1.1286 + for (int index = 0; index < fPaintCount; index++) { 1.1287 + // const SkPaint& paint = fPaints[index]; 1.1288 + result += sizeof(SkPaint); // paint->size(); 1.1289 + } 1.1290 + *size = result; 1.1291 + return fPaintCount; 1.1292 +} 1.1293 + 1.1294 +int SkPicturePlayback::paths(size_t* size) { 1.1295 + size_t result = 0; 1.1296 + for (int index = 0; index < fPathCount; index++) { 1.1297 + const SkPath& path = fPaths[index]; 1.1298 + result += path.flatten(NULL); 1.1299 + } 1.1300 + *size = result; 1.1301 + return fPathCount; 1.1302 +} 1.1303 +#endif 1.1304 + 1.1305 +#ifdef SK_DEBUG_DUMP 1.1306 +void SkPicturePlayback::dumpBitmap(const SkBitmap& bitmap) const { 1.1307 + char pBuffer[DUMP_BUFFER_SIZE]; 1.1308 + char* bufferPtr = pBuffer; 1.1309 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1310 + "BitmapData bitmap%p = {", &bitmap); 1.1311 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1312 + "{kWidth, %d}, ", bitmap.width()); 1.1313 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1314 + "{kHeight, %d}, ", bitmap.height()); 1.1315 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1316 + "{kRowBytes, %d}, ", bitmap.rowBytes()); 1.1317 +// start here; 1.1318 + SkDebugf("%s{0}};\n", pBuffer); 1.1319 +} 1.1320 + 1.1321 +void dumpMatrix(const SkMatrix& matrix) const { 1.1322 + SkMatrix defaultMatrix; 1.1323 + defaultMatrix.reset(); 1.1324 + char pBuffer[DUMP_BUFFER_SIZE]; 1.1325 + char* bufferPtr = pBuffer; 1.1326 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1327 + "MatrixData matrix%p = {", &matrix); 1.1328 + SkScalar scaleX = matrix.getScaleX(); 1.1329 + if (scaleX != defaultMatrix.getScaleX()) 1.1330 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1331 + "{kScaleX, %g}, ", SkScalarToFloat(scaleX)); 1.1332 + SkScalar scaleY = matrix.getScaleY(); 1.1333 + if (scaleY != defaultMatrix.getScaleY()) 1.1334 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1335 + "{kScaleY, %g}, ", SkScalarToFloat(scaleY)); 1.1336 + SkScalar skewX = matrix.getSkewX(); 1.1337 + if (skewX != defaultMatrix.getSkewX()) 1.1338 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1339 + "{kSkewX, %g}, ", SkScalarToFloat(skewX)); 1.1340 + SkScalar skewY = matrix.getSkewY(); 1.1341 + if (skewY != defaultMatrix.getSkewY()) 1.1342 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1343 + "{kSkewY, %g}, ", SkScalarToFloat(skewY)); 1.1344 + SkScalar translateX = matrix.getTranslateX(); 1.1345 + if (translateX != defaultMatrix.getTranslateX()) 1.1346 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1347 + "{kTranslateX, %g}, ", SkScalarToFloat(translateX)); 1.1348 + SkScalar translateY = matrix.getTranslateY(); 1.1349 + if (translateY != defaultMatrix.getTranslateY()) 1.1350 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1351 + "{kTranslateY, %g}, ", SkScalarToFloat(translateY)); 1.1352 + SkScalar perspX = matrix.getPerspX(); 1.1353 + if (perspX != defaultMatrix.getPerspX()) 1.1354 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1355 + "{kPerspX, %g}, ", perspX); 1.1356 + SkScalar perspY = matrix.getPerspY(); 1.1357 + if (perspY != defaultMatrix.getPerspY()) 1.1358 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1359 + "{kPerspY, %g}, ", perspY); 1.1360 + SkDebugf("%s{0}};\n", pBuffer); 1.1361 +} 1.1362 + 1.1363 +void dumpPaint(const SkPaint& paint) const { 1.1364 + SkPaint defaultPaint; 1.1365 + char pBuffer[DUMP_BUFFER_SIZE]; 1.1366 + char* bufferPtr = pBuffer; 1.1367 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1368 + "PaintPointers paintPtrs%p = {", &paint); 1.1369 + const SkTypeface* typeface = paint.getTypeface(); 1.1370 + if (typeface != defaultPaint.getTypeface()) 1.1371 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1372 + "{kTypeface, %p}, ", typeface); 1.1373 + const SkPathEffect* pathEffect = paint.getPathEffect(); 1.1374 + if (pathEffect != defaultPaint.getPathEffect()) 1.1375 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1376 + "{kPathEffect, %p}, ", pathEffect); 1.1377 + const SkShader* shader = paint.getShader(); 1.1378 + if (shader != defaultPaint.getShader()) 1.1379 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1380 + "{kShader, %p}, ", shader); 1.1381 + const SkXfermode* xfermode = paint.getXfermode(); 1.1382 + if (xfermode != defaultPaint.getXfermode()) 1.1383 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1384 + "{kXfermode, %p}, ", xfermode); 1.1385 + const SkMaskFilter* maskFilter = paint.getMaskFilter(); 1.1386 + if (maskFilter != defaultPaint.getMaskFilter()) 1.1387 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1388 + "{kMaskFilter, %p}, ", maskFilter); 1.1389 + const SkColorFilter* colorFilter = paint.getColorFilter(); 1.1390 + if (colorFilter != defaultPaint.getColorFilter()) 1.1391 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1392 + "{kColorFilter, %p}, ", colorFilter); 1.1393 + const SkRasterizer* rasterizer = paint.getRasterizer(); 1.1394 + if (rasterizer != defaultPaint.getRasterizer()) 1.1395 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1396 + "{kRasterizer, %p}, ", rasterizer); 1.1397 + const SkDrawLooper* drawLooper = paint.getLooper(); 1.1398 + if (drawLooper != defaultPaint.getLooper()) 1.1399 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1400 + "{kDrawLooper, %p}, ", drawLooper); 1.1401 + SkDebugf("%s{0}};\n", pBuffer); 1.1402 + bufferPtr = pBuffer; 1.1403 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1404 + "PaintScalars paintScalars%p = {", &paint); 1.1405 + SkScalar textSize = paint.getTextSize(); 1.1406 + if (textSize != defaultPaint.getTextSize()) 1.1407 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1408 + "{kTextSize, %g}, ", SkScalarToFloat(textSize)); 1.1409 + SkScalar textScaleX = paint.getTextScaleX(); 1.1410 + if (textScaleX != defaultPaint.getTextScaleX()) 1.1411 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1412 + "{kTextScaleX, %g}, ", SkScalarToFloat(textScaleX)); 1.1413 + SkScalar textSkewX = paint.getTextSkewX(); 1.1414 + if (textSkewX != defaultPaint.getTextSkewX()) 1.1415 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1416 + "{kTextSkewX, %g}, ", SkScalarToFloat(textSkewX)); 1.1417 + SkScalar strokeWidth = paint.getStrokeWidth(); 1.1418 + if (strokeWidth != defaultPaint.getStrokeWidth()) 1.1419 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1420 + "{kStrokeWidth, %g}, ", SkScalarToFloat(strokeWidth)); 1.1421 + SkScalar strokeMiter = paint.getStrokeMiter(); 1.1422 + if (strokeMiter != defaultPaint.getStrokeMiter()) 1.1423 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1424 + "{kStrokeMiter, %g}, ", SkScalarToFloat(strokeMiter)); 1.1425 + SkDebugf("%s{0}};\n", pBuffer); 1.1426 + bufferPtr = pBuffer; 1.1427 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1428 + "PaintInts = paintInts%p = {", &paint); 1.1429 + unsigned color = paint.getColor(); 1.1430 + if (color != defaultPaint.getColor()) 1.1431 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1432 + "{kColor, 0x%x}, ", color); 1.1433 + unsigned flags = paint.getFlags(); 1.1434 + if (flags != defaultPaint.getFlags()) 1.1435 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1436 + "{kFlags, 0x%x}, ", flags); 1.1437 + int align = paint.getTextAlign(); 1.1438 + if (align != defaultPaint.getTextAlign()) 1.1439 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1440 + "{kAlign, 0x%x}, ", align); 1.1441 + int strokeCap = paint.getStrokeCap(); 1.1442 + if (strokeCap != defaultPaint.getStrokeCap()) 1.1443 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1444 + "{kStrokeCap, 0x%x}, ", strokeCap); 1.1445 + int strokeJoin = paint.getStrokeJoin(); 1.1446 + if (strokeJoin != defaultPaint.getStrokeJoin()) 1.1447 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1448 + "{kAlign, 0x%x}, ", strokeJoin); 1.1449 + int style = paint.getStyle(); 1.1450 + if (style != defaultPaint.getStyle()) 1.1451 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1452 + "{kStyle, 0x%x}, ", style); 1.1453 + int textEncoding = paint.getTextEncoding(); 1.1454 + if (textEncoding != defaultPaint.getTextEncoding()) 1.1455 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1456 + "{kTextEncoding, 0x%x}, ", textEncoding); 1.1457 + SkDebugf("%s{0}};\n", pBuffer); 1.1458 + 1.1459 + SkDebugf("PaintData paint%p = {paintPtrs%p, paintScalars%p, paintInts%p};\n", 1.1460 + &paint, &paint, &paint, &paint); 1.1461 +} 1.1462 + 1.1463 +void SkPicturePlayback::dumpPath(const SkPath& path) const { 1.1464 + SkDebugf("path dump unimplemented\n"); 1.1465 +} 1.1466 + 1.1467 +void SkPicturePlayback::dumpPicture(const SkPicture& picture) const { 1.1468 + SkDebugf("picture dump unimplemented\n"); 1.1469 +} 1.1470 + 1.1471 +void SkPicturePlayback::dumpRegion(const SkRegion& region) const { 1.1472 + SkDebugf("region dump unimplemented\n"); 1.1473 +} 1.1474 + 1.1475 +int SkPicturePlayback::dumpDrawType(char* bufferPtr, char* buffer, DrawType drawType) { 1.1476 + return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer), 1.1477 + "k%s, ", DrawTypeToString(drawType)); 1.1478 +} 1.1479 + 1.1480 +int SkPicturePlayback::dumpInt(char* bufferPtr, char* buffer, char* name) { 1.1481 + return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer), 1.1482 + "%s:%d, ", name, getInt()); 1.1483 +} 1.1484 + 1.1485 +int SkPicturePlayback::dumpRect(char* bufferPtr, char* buffer, char* name) { 1.1486 + const SkRect* rect = fReader.skipRect(); 1.1487 + return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer), 1.1488 + "%s:{l:%g t:%g r:%g b:%g}, ", name, SkScalarToFloat(rect.fLeft), 1.1489 + SkScalarToFloat(rect.fTop), 1.1490 + SkScalarToFloat(rect.fRight), SkScalarToFloat(rect.fBottom)); 1.1491 +} 1.1492 + 1.1493 +int SkPicturePlayback::dumpPoint(char* bufferPtr, char* buffer, char* name) { 1.1494 + SkPoint pt; 1.1495 + getPoint(&pt); 1.1496 + return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer), 1.1497 + "%s:{x:%g y:%g}, ", name, SkScalarToFloat(pt.fX), 1.1498 + SkScalarToFloat(pt.fY)); 1.1499 +} 1.1500 + 1.1501 +void SkPicturePlayback::dumpPointArray(char** bufferPtrPtr, char* buffer, int count) { 1.1502 + char* bufferPtr = *bufferPtrPtr; 1.1503 + const SkPoint* pts = (const SkPoint*)fReadStream.getAtPos(); 1.1504 + fReadStream.skip(sizeof(SkPoint) * count); 1.1505 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer), 1.1506 + "count:%d {", count); 1.1507 + for (int index = 0; index < count; index++) 1.1508 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer), 1.1509 + "{x:%g y:%g}, ", SkScalarToFloat(pts[index].fX), 1.1510 + SkScalarToFloat(pts[index].fY)); 1.1511 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer), 1.1512 + "} "); 1.1513 + *bufferPtrPtr = bufferPtr; 1.1514 +} 1.1515 + 1.1516 +int SkPicturePlayback::dumpPtr(char* bufferPtr, char* buffer, char* name, void* ptr) { 1.1517 + return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer), 1.1518 + "%s:%p, ", name, ptr); 1.1519 +} 1.1520 + 1.1521 +int SkPicturePlayback::dumpRectPtr(char* bufferPtr, char* buffer, char* name) { 1.1522 + char result; 1.1523 + fReadStream.read(&result, sizeof(result)); 1.1524 + if (result) 1.1525 + return dumpRect(bufferPtr, buffer, name); 1.1526 + else 1.1527 + return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer), 1.1528 + "%s:NULL, ", name); 1.1529 +} 1.1530 + 1.1531 +int SkPicturePlayback::dumpScalar(char* bufferPtr, char* buffer, char* name) { 1.1532 + return snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - buffer), 1.1533 + "%s:%d, ", name, getScalar()); 1.1534 +} 1.1535 + 1.1536 +void SkPicturePlayback::dumpText(char** bufferPtrPtr, char* buffer) { 1.1537 + char* bufferPtr = *bufferPtrPtr; 1.1538 + int length = getInt(); 1.1539 + bufferPtr += dumpDrawType(bufferPtr, buffer); 1.1540 + fReadStream.skipToAlign4(); 1.1541 + char* text = (char*) fReadStream.getAtPos(); 1.1542 + fReadStream.skip(length); 1.1543 + bufferPtr += dumpInt(bufferPtr, buffer, "length"); 1.1544 + int limit = DUMP_BUFFER_SIZE - (bufferPtr - buffer) - 2; 1.1545 + length >>= 1; 1.1546 + if (limit > length) 1.1547 + limit = length; 1.1548 + if (limit > 0) { 1.1549 + *bufferPtr++ = '"'; 1.1550 + for (int index = 0; index < limit; index++) { 1.1551 + *bufferPtr++ = *(unsigned short*) text; 1.1552 + text += sizeof(unsigned short); 1.1553 + } 1.1554 + *bufferPtr++ = '"'; 1.1555 + } 1.1556 + *bufferPtrPtr = bufferPtr; 1.1557 +} 1.1558 + 1.1559 +#define DUMP_DRAWTYPE(drawType) \ 1.1560 + bufferPtr += dumpDrawType(bufferPtr, buffer, drawType) 1.1561 + 1.1562 +#define DUMP_INT(name) \ 1.1563 + bufferPtr += dumpInt(bufferPtr, buffer, #name) 1.1564 + 1.1565 +#define DUMP_RECT_PTR(name) \ 1.1566 + bufferPtr += dumpRectPtr(bufferPtr, buffer, #name) 1.1567 + 1.1568 +#define DUMP_POINT(name) \ 1.1569 + bufferPtr += dumpRect(bufferPtr, buffer, #name) 1.1570 + 1.1571 +#define DUMP_RECT(name) \ 1.1572 + bufferPtr += dumpRect(bufferPtr, buffer, #name) 1.1573 + 1.1574 +#define DUMP_POINT_ARRAY(count) \ 1.1575 + dumpPointArray(&bufferPtr, buffer, count) 1.1576 + 1.1577 +#define DUMP_PTR(name, ptr) \ 1.1578 + bufferPtr += dumpPtr(bufferPtr, buffer, #name, (void*) ptr) 1.1579 + 1.1580 +#define DUMP_SCALAR(name) \ 1.1581 + bufferPtr += dumpScalar(bufferPtr, buffer, #name) 1.1582 + 1.1583 +#define DUMP_TEXT() \ 1.1584 + dumpText(&bufferPtr, buffer) 1.1585 + 1.1586 +void SkPicturePlayback::dumpStream() { 1.1587 + SkDebugf("RecordStream stream = {\n"); 1.1588 + DrawType drawType; 1.1589 + TextContainer text; 1.1590 + fReadStream.rewind(); 1.1591 + char buffer[DUMP_BUFFER_SIZE], * bufferPtr; 1.1592 + while (fReadStream.read(&drawType, sizeof(drawType))) { 1.1593 + bufferPtr = buffer; 1.1594 + DUMP_DRAWTYPE(drawType); 1.1595 + switch (drawType) { 1.1596 + case CLIP_PATH: { 1.1597 + DUMP_PTR(SkPath, &getPath()); 1.1598 + DUMP_INT(SkRegion::Op); 1.1599 + DUMP_INT(offsetToRestore); 1.1600 + } break; 1.1601 + case CLIP_REGION: { 1.1602 + DUMP_INT(SkRegion::Op); 1.1603 + DUMP_INT(offsetToRestore); 1.1604 + } break; 1.1605 + case CLIP_RECT: { 1.1606 + DUMP_RECT(rect); 1.1607 + DUMP_INT(SkRegion::Op); 1.1608 + DUMP_INT(offsetToRestore); 1.1609 + } break; 1.1610 + case CONCAT: 1.1611 + break; 1.1612 + case DRAW_BITMAP: { 1.1613 + DUMP_PTR(SkPaint, getPaint()); 1.1614 + DUMP_PTR(SkBitmap, &getBitmap()); 1.1615 + DUMP_SCALAR(left); 1.1616 + DUMP_SCALAR(top); 1.1617 + } break; 1.1618 + case DRAW_PAINT: 1.1619 + DUMP_PTR(SkPaint, getPaint()); 1.1620 + break; 1.1621 + case DRAW_PATH: { 1.1622 + DUMP_PTR(SkPaint, getPaint()); 1.1623 + DUMP_PTR(SkPath, &getPath()); 1.1624 + } break; 1.1625 + case DRAW_PICTURE: { 1.1626 + DUMP_PTR(SkPicture, &getPicture()); 1.1627 + } break; 1.1628 + case DRAW_POINTS: { 1.1629 + DUMP_PTR(SkPaint, getPaint()); 1.1630 + (void)getInt(); // PointMode 1.1631 + size_t count = getInt(); 1.1632 + fReadStream.skipToAlign4(); 1.1633 + DUMP_POINT_ARRAY(count); 1.1634 + } break; 1.1635 + case DRAW_POS_TEXT: { 1.1636 + DUMP_PTR(SkPaint, getPaint()); 1.1637 + DUMP_TEXT(); 1.1638 + size_t points = getInt(); 1.1639 + fReadStream.skipToAlign4(); 1.1640 + DUMP_POINT_ARRAY(points); 1.1641 + } break; 1.1642 + case DRAW_POS_TEXT_H: { 1.1643 + DUMP_PTR(SkPaint, getPaint()); 1.1644 + DUMP_TEXT(); 1.1645 + size_t points = getInt(); 1.1646 + fReadStream.skipToAlign4(); 1.1647 + DUMP_SCALAR(top); 1.1648 + DUMP_SCALAR(bottom); 1.1649 + DUMP_SCALAR(constY); 1.1650 + DUMP_POINT_ARRAY(points); 1.1651 + } break; 1.1652 + case DRAW_RECT: { 1.1653 + DUMP_PTR(SkPaint, getPaint()); 1.1654 + DUMP_RECT(rect); 1.1655 + } break; 1.1656 + case DRAW_SPRITE: { 1.1657 + DUMP_PTR(SkPaint, getPaint()); 1.1658 + DUMP_PTR(SkBitmap, &getBitmap()); 1.1659 + DUMP_SCALAR(left); 1.1660 + DUMP_SCALAR(top); 1.1661 + } break; 1.1662 + case DRAW_TEXT: { 1.1663 + DUMP_PTR(SkPaint, getPaint()); 1.1664 + DUMP_TEXT(); 1.1665 + DUMP_SCALAR(x); 1.1666 + DUMP_SCALAR(y); 1.1667 + } break; 1.1668 + case DRAW_TEXT_ON_PATH: { 1.1669 + DUMP_PTR(SkPaint, getPaint()); 1.1670 + DUMP_TEXT(); 1.1671 + DUMP_PTR(SkPath, &getPath()); 1.1672 + } break; 1.1673 + case RESTORE: 1.1674 + break; 1.1675 + case ROTATE: 1.1676 + DUMP_SCALAR(rotate); 1.1677 + break; 1.1678 + case SAVE: 1.1679 + DUMP_INT(SkCanvas::SaveFlags); 1.1680 + break; 1.1681 + case SAVE_LAYER: { 1.1682 + DUMP_RECT_PTR(layer); 1.1683 + DUMP_PTR(SkPaint, getPaint()); 1.1684 + DUMP_INT(SkCanvas::SaveFlags); 1.1685 + } break; 1.1686 + case SCALE: { 1.1687 + DUMP_SCALAR(sx); 1.1688 + DUMP_SCALAR(sy); 1.1689 + } break; 1.1690 + case SKEW: { 1.1691 + DUMP_SCALAR(sx); 1.1692 + DUMP_SCALAR(sy); 1.1693 + } break; 1.1694 + case TRANSLATE: { 1.1695 + DUMP_SCALAR(dx); 1.1696 + DUMP_SCALAR(dy); 1.1697 + } break; 1.1698 + default: 1.1699 + SkASSERT(0); 1.1700 + } 1.1701 + SkDebugf("%s\n", buffer); 1.1702 + } 1.1703 +} 1.1704 + 1.1705 +void SkPicturePlayback::dump() const { 1.1706 + char pBuffer[DUMP_BUFFER_SIZE]; 1.1707 + char* bufferPtr = pBuffer; 1.1708 + int index; 1.1709 + if (fBitmapCount > 0) 1.1710 + SkDebugf("// bitmaps (%d)\n", fBitmapCount); 1.1711 + for (index = 0; index < fBitmapCount; index++) { 1.1712 + const SkBitmap& bitmap = fBitmaps[index]; 1.1713 + dumpBitmap(bitmap); 1.1714 + } 1.1715 + if (fBitmapCount > 0) 1.1716 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1717 + "Bitmaps bitmaps = {"); 1.1718 + for (index = 0; index < fBitmapCount; index++) 1.1719 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1720 + "bitmap%p, ", &fBitmaps[index]); 1.1721 + if (fBitmapCount > 0) 1.1722 + SkDebugf("%s0};\n", pBuffer); 1.1723 + 1.1724 + 1.1725 + if (fPaintCount > 0) 1.1726 + SkDebugf("// paints (%d)\n", fPaintCount); 1.1727 + for (index = 0; index < fPaintCount; index++) { 1.1728 + const SkPaint& paint = fPaints[index]; 1.1729 + dumpPaint(paint); 1.1730 + } 1.1731 + bufferPtr = pBuffer; 1.1732 + if (fPaintCount > 0) 1.1733 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1734 + "Paints paints = {"); 1.1735 + for (index = 0; index < fPaintCount; index++) 1.1736 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1737 + "paint%p, ", &fPaints[index]); 1.1738 + if (fPaintCount > 0) 1.1739 + SkDebugf("%s0};\n", pBuffer); 1.1740 + 1.1741 + for (index = 0; index < fPathCount; index++) { 1.1742 + const SkPath& path = fPaths[index]; 1.1743 + dumpPath(path); 1.1744 + } 1.1745 + bufferPtr = pBuffer; 1.1746 + if (fPathCount > 0) 1.1747 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1748 + "Paths paths = {"); 1.1749 + for (index = 0; index < fPathCount; index++) 1.1750 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1751 + "path%p, ", &fPaths[index]); 1.1752 + if (fPathCount > 0) 1.1753 + SkDebugf("%s0};\n", pBuffer); 1.1754 + 1.1755 + for (index = 0; index < fPictureCount; index++) { 1.1756 + dumpPicture(*fPictureRefs[index]); 1.1757 + } 1.1758 + bufferPtr = pBuffer; 1.1759 + if (fPictureCount > 0) 1.1760 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1761 + "Pictures pictures = {"); 1.1762 + for (index = 0; index < fPictureCount; index++) 1.1763 + bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 1.1764 + "picture%p, ", fPictureRefs[index]); 1.1765 + if (fPictureCount > 0) 1.1766 + SkDebugf("%s0};\n", pBuffer); 1.1767 + 1.1768 + const_cast<SkPicturePlayback*>(this)->dumpStream(); 1.1769 +} 1.1770 + 1.1771 +#endif