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