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