Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(249)

Side by Side Diff: src/core/SkPicturePlayback.cpp

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

Powered by Google App Engine
This is Rietveld 408576698