1ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips/*
2ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips * Copyright 2014 Google Inc.
3ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips *
4ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips * Use of this source code is governed by a BSD-style license that can be
5ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips * found in the LICENSE file.
6ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips */
7ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips
8ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips#include "SkCanvas.h"
9b3c9d1c33caf325aada244204215eb790c228c12dandov#include "SkPatchUtils.h"
10ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips#include "SkPictureData.h"
11ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips#include "SkPicturePlayback.h"
12ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips#include "SkPictureRecord.h"
13ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips#include "SkPictureStateTree.h"
14ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips#include "SkReader32.h"
15b7425173f96e93b090787e2386ba5f022b6c2869fmalita#include "SkTextBlob.h"
16ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips#include "SkTDArray.h"
17ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips#include "SkTypes.h"
18ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips
19ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips/*
201ad00e4b245d464c16ba78bdaa377281f29972cdrobertphillips * Read the next op code and chunk size from 'reader'. The returned size
211ad00e4b245d464c16ba78bdaa377281f29972cdrobertphillips * is the entire size of the chunk (including the opcode). Thus, the
221ad00e4b245d464c16ba78bdaa377281f29972cdrobertphillips * offset just prior to calling ReadOpAndSize + 'size' is the offset
231ad00e4b245d464c16ba78bdaa377281f29972cdrobertphillips * to the next chunk's op code. This also means that the size of a chunk
241ad00e4b245d464c16ba78bdaa377281f29972cdrobertphillips * with no arguments (just an opcode) will be 4.
251ad00e4b245d464c16ba78bdaa377281f29972cdrobertphillips */
261ad00e4b245d464c16ba78bdaa377281f29972cdrobertphillipsDrawType SkPicturePlayback::ReadOpAndSize(SkReader32* reader, uint32_t* size) {
27ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    uint32_t temp = reader->readInt();
28ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    uint32_t op;
29ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    if (((uint8_t)temp) == temp) {
30ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        // old skp file - no size information
31ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        op = temp;
32ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        *size = 0;
33ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    } else {
34ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        UNPACK_8_24(temp, op, *size);
35ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        if (MASK_24 == *size) {
36ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            *size = reader->readInt();
37ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        }
38ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    }
39ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    return (DrawType)op;
40ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips}
41ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips
42ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips
433afef1f75f710b8f183113cdc5188416f7d01f28robertphillipsstatic const SkRect* get_rect_ptr(SkReader32* reader) {
443afef1f75f710b8f183113cdc5188416f7d01f28robertphillips    if (reader->readBool()) {
453afef1f75f710b8f183113cdc5188416f7d01f28robertphillips        return &reader->skipT<SkRect>();
46ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    } else {
47ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        return NULL;
48ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    }
49ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips}
50ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips
51ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillipsclass TextContainer {
52ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillipspublic:
53ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    size_t length() { return fByteLength; }
54ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    const void* text() { return (const void*)fText; }
55ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    size_t fByteLength;
56ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    const char* fText;
57ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips};
58ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips
59ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillipsvoid get_text(SkReader32* reader, TextContainer* text) {
60ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    size_t length = text->fByteLength = reader->readInt();
61ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    text->fText = (const char*)reader->skip(length);
62ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips}
63ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips
64eeb1f15891ee9f96f2c5d6e1c3d5a656208f3760mtklein// FIXME: SkBitmaps are stateful, so we need to copy them to play back in multiple threads.
65eeb1f15891ee9f96f2c5d6e1c3d5a656208f3760mtkleinstatic SkBitmap shallow_copy(const SkBitmap& bitmap) {
66eeb1f15891ee9f96f2c5d6e1c3d5a656208f3760mtklein    return bitmap;
67eeb1f15891ee9f96f2c5d6e1c3d5a656208f3760mtklein}
68eeb1f15891ee9f96f2c5d6e1c3d5a656208f3760mtklein
69ec66e6264de5110802c3d9927380d913242c9d5frobertphillipsconst SkPicture::OperationList* SkPicturePlayback::getActiveOps(const SkCanvas* canvas) {
70ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips
716142609b22814283210f79d698182b651a93136crobertphillips    if (fUseBBH) {
721ad00e4b245d464c16ba78bdaa377281f29972cdrobertphillips        SkRect clipBounds;
731ad00e4b245d464c16ba78bdaa377281f29972cdrobertphillips        if (canvas->getClipBounds(&clipBounds)) {
74533eb782edaa0b6fece6166d3001edf72ec39f11mtklein            return fPictureData->getActiveOps(clipBounds);
75ec66e6264de5110802c3d9927380d913242c9d5frobertphillips        }
76533eb782edaa0b6fece6166d3001edf72ec39f11mtklein    }
77ec66e6264de5110802c3d9927380d913242c9d5frobertphillips
78ec66e6264de5110802c3d9927380d913242c9d5frobertphillips    return NULL;
79ec66e6264de5110802c3d9927380d913242c9d5frobertphillips}
80ec66e6264de5110802c3d9927380d913242c9d5frobertphillips
81ec66e6264de5110802c3d9927380d913242c9d5frobertphillips// Initialize the state tree iterator. Return false if there is nothing left to draw.
82533eb782edaa0b6fece6166d3001edf72ec39f11mtkleinbool SkPicturePlayback::initIterator(SkPictureStateTree::Iterator* iter,
83ec66e6264de5110802c3d9927380d913242c9d5frobertphillips                                     SkCanvas* canvas,
84ec66e6264de5110802c3d9927380d913242c9d5frobertphillips                                     const SkPicture::OperationList *activeOpsList) {
85ec66e6264de5110802c3d9927380d913242c9d5frobertphillips
8649f085dddff10473b6ebf832a974288300224e60bsalomon    if (activeOpsList) {
87ec66e6264de5110802c3d9927380d913242c9d5frobertphillips        if (0 == activeOpsList->numOps()) {
88ec66e6264de5110802c3d9927380d913242c9d5frobertphillips            return false;  // nothing to draw
89ec66e6264de5110802c3d9927380d913242c9d5frobertphillips        }
90ec66e6264de5110802c3d9927380d913242c9d5frobertphillips
916142609b22814283210f79d698182b651a93136crobertphillips        fPictureData->initIterator(iter, activeOpsList->fOps, canvas);
92ec66e6264de5110802c3d9927380d913242c9d5frobertphillips    }
93ec66e6264de5110802c3d9927380d913242c9d5frobertphillips
94ec66e6264de5110802c3d9927380d913242c9d5frobertphillips    return true;
95ec66e6264de5110802c3d9927380d913242c9d5frobertphillips}
96ec66e6264de5110802c3d9927380d913242c9d5frobertphillips
97ec66e6264de5110802c3d9927380d913242c9d5frobertphillips// If 'iter' is valid use it to skip forward through the picture.
98ec66e6264de5110802c3d9927380d913242c9d5frobertphillipsvoid SkPicturePlayback::StepIterator(SkPictureStateTree::Iterator* iter, SkReader32* reader) {
99ec66e6264de5110802c3d9927380d913242c9d5frobertphillips    if (iter->isValid()) {
100ec66e6264de5110802c3d9927380d913242c9d5frobertphillips        uint32_t skipTo = iter->nextDraw();
101ec66e6264de5110802c3d9927380d913242c9d5frobertphillips        if (SkPictureStateTree::Iterator::kDrawComplete == skipTo) {
102ec66e6264de5110802c3d9927380d913242c9d5frobertphillips            reader->setOffset(reader->size());  // skip to end
103ec66e6264de5110802c3d9927380d913242c9d5frobertphillips        } else {
104ec66e6264de5110802c3d9927380d913242c9d5frobertphillips            reader->setOffset(skipTo);
105ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        }
106ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    }
107ec66e6264de5110802c3d9927380d913242c9d5frobertphillips}
108ec66e6264de5110802c3d9927380d913242c9d5frobertphillips
109ec66e6264de5110802c3d9927380d913242c9d5frobertphillips// Update the iterator and state tree to catch up with the skipped ops.
110ec66e6264de5110802c3d9927380d913242c9d5frobertphillipsvoid SkPicturePlayback::SkipIterTo(SkPictureStateTree::Iterator* iter,
111ec66e6264de5110802c3d9927380d913242c9d5frobertphillips                                   SkReader32* reader,
112ec66e6264de5110802c3d9927380d913242c9d5frobertphillips                                   uint32_t skipTo) {
113ec66e6264de5110802c3d9927380d913242c9d5frobertphillips    SkASSERT(skipTo <= reader->size());
114ec66e6264de5110802c3d9927380d913242c9d5frobertphillips    SkASSERT(reader->offset() <= skipTo); // should only be skipping forward
115ec66e6264de5110802c3d9927380d913242c9d5frobertphillips
116ec66e6264de5110802c3d9927380d913242c9d5frobertphillips    if (iter->isValid()) {
117ec66e6264de5110802c3d9927380d913242c9d5frobertphillips        // If using a bounding box hierarchy, advance the state tree
118ec66e6264de5110802c3d9927380d913242c9d5frobertphillips        // iterator until at or after skipTo
119ec66e6264de5110802c3d9927380d913242c9d5frobertphillips        uint32_t adjustedSkipTo;
120ec66e6264de5110802c3d9927380d913242c9d5frobertphillips        do {
121ec66e6264de5110802c3d9927380d913242c9d5frobertphillips            adjustedSkipTo = iter->nextDraw();
122ec66e6264de5110802c3d9927380d913242c9d5frobertphillips        } while (adjustedSkipTo < skipTo);
123ec66e6264de5110802c3d9927380d913242c9d5frobertphillips        skipTo = adjustedSkipTo;
124ec66e6264de5110802c3d9927380d913242c9d5frobertphillips    }
125ec66e6264de5110802c3d9927380d913242c9d5frobertphillips    if (SkPictureStateTree::Iterator::kDrawComplete == skipTo) {
126ec66e6264de5110802c3d9927380d913242c9d5frobertphillips        reader->setOffset(reader->size());  // skip to end
127ec66e6264de5110802c3d9927380d913242c9d5frobertphillips    } else {
128ec66e6264de5110802c3d9927380d913242c9d5frobertphillips        reader->setOffset(skipTo);
129ec66e6264de5110802c3d9927380d913242c9d5frobertphillips    }
130ec66e6264de5110802c3d9927380d913242c9d5frobertphillips}
131ec66e6264de5110802c3d9927380d913242c9d5frobertphillips
132ec66e6264de5110802c3d9927380d913242c9d5frobertphillipsvoid SkPicturePlayback::draw(SkCanvas* canvas, SkDrawPictureCallback* callback) {
133ec66e6264de5110802c3d9927380d913242c9d5frobertphillips    AutoResetOpID aroi(this);
134ec66e6264de5110802c3d9927380d913242c9d5frobertphillips    SkASSERT(0 == fCurOffset);
135ec66e6264de5110802c3d9927380d913242c9d5frobertphillips
136ec66e6264de5110802c3d9927380d913242c9d5frobertphillips    SkAutoTDelete<const SkPicture::OperationList> activeOpsList(this->getActiveOps(canvas));
137ec66e6264de5110802c3d9927380d913242c9d5frobertphillips    SkPictureStateTree::Iterator it;
138ec66e6264de5110802c3d9927380d913242c9d5frobertphillips
139ec66e6264de5110802c3d9927380d913242c9d5frobertphillips    if (!this->initIterator(&it, canvas, activeOpsList.get())) {
140ec66e6264de5110802c3d9927380d913242c9d5frobertphillips        return;  // nothing to draw
141ec66e6264de5110802c3d9927380d913242c9d5frobertphillips    }
142ec66e6264de5110802c3d9927380d913242c9d5frobertphillips
143ec66e6264de5110802c3d9927380d913242c9d5frobertphillips    SkReader32 reader(fPictureData->opData()->bytes(), fPictureData->opData()->size());
144ec66e6264de5110802c3d9927380d913242c9d5frobertphillips
145ec66e6264de5110802c3d9927380d913242c9d5frobertphillips    StepIterator(&it, &reader);
146ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips
147ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    // Record this, so we can concat w/ it if we encounter a setMatrix()
148ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    SkMatrix initialMatrix = canvas->getTotalMatrix();
149ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips
150ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    SkAutoCanvasRestore acr(canvas, false);
151ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips
152ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    while (!reader.eof()) {
15349f085dddff10473b6ebf832a974288300224e60bsalomon        if (callback && callback->abortDrawing()) {
154ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            return;
155ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        }
156ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips
157ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        fCurOffset = reader.offset();
158ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        uint32_t size;
1591ad00e4b245d464c16ba78bdaa377281f29972cdrobertphillips        DrawType op = ReadOpAndSize(&reader, &size);
160ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        if (NOOP == op) {
161ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            // NOOPs are to be ignored - do not propagate them any further
162ec66e6264de5110802c3d9927380d913242c9d5frobertphillips            SkipIterTo(&it, &reader, fCurOffset + size);
163ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            continue;
164ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        }
165ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips
1663afef1f75f710b8f183113cdc5188416f7d01f28robertphillips        this->handleOp(&reader, op, size, canvas, initialMatrix);
1673afef1f75f710b8f183113cdc5188416f7d01f28robertphillips
168ec66e6264de5110802c3d9927380d913242c9d5frobertphillips        StepIterator(&it, &reader);
1693afef1f75f710b8f183113cdc5188416f7d01f28robertphillips    }
1703afef1f75f710b8f183113cdc5188416f7d01f28robertphillips}
1713afef1f75f710b8f183113cdc5188416f7d01f28robertphillips
172533eb782edaa0b6fece6166d3001edf72ec39f11mtkleinvoid SkPicturePlayback::handleOp(SkReader32* reader,
173533eb782edaa0b6fece6166d3001edf72ec39f11mtklein                                 DrawType op,
174533eb782edaa0b6fece6166d3001edf72ec39f11mtklein                                 uint32_t size,
1753afef1f75f710b8f183113cdc5188416f7d01f28robertphillips                                 SkCanvas* canvas,
1763afef1f75f710b8f183113cdc5188416f7d01f28robertphillips                                 const SkMatrix& initialMatrix) {
1773afef1f75f710b8f183113cdc5188416f7d01f28robertphillips    switch (op) {
178ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case CLIP_PATH: {
179ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPath& path = fPictureData->getPath(reader);
1803afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            uint32_t packed = reader->readInt();
181ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
182ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            bool doAA = ClipParams_unpackDoAA(packed);
1833afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            size_t offsetToRestore = reader->readInt();
1843afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
185ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->clipPath(path, regionOp, doAA);
186ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            if (canvas->isClipEmpty() && offsetToRestore) {
1873afef1f75f710b8f183113cdc5188416f7d01f28robertphillips                reader->setOffset(offsetToRestore);
188ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            }
189ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
190ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case CLIP_REGION: {
191ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkRegion region;
1923afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            reader->readRegion(&region);
1933afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            uint32_t packed = reader->readInt();
194ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
1953afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            size_t offsetToRestore = reader->readInt();
1963afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
197ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->clipRegion(region, regionOp);
198ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            if (canvas->isClipEmpty() && offsetToRestore) {
1993afef1f75f710b8f183113cdc5188416f7d01f28robertphillips                reader->setOffset(offsetToRestore);
200ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            }
201ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
202ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case CLIP_RECT: {
2033afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkRect& rect = reader->skipT<SkRect>();
2043afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            uint32_t packed = reader->readInt();
205ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
206ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            bool doAA = ClipParams_unpackDoAA(packed);
2073afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            size_t offsetToRestore = reader->readInt();
2083afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
209ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->clipRect(rect, regionOp, doAA);
210ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            if (canvas->isClipEmpty() && offsetToRestore) {
2113afef1f75f710b8f183113cdc5188416f7d01f28robertphillips                reader->setOffset(offsetToRestore);
212ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            }
213ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
214ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case CLIP_RRECT: {
215ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkRRect rrect;
2163afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            reader->readRRect(&rrect);
2173afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            uint32_t packed = reader->readInt();
218ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
219ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            bool doAA = ClipParams_unpackDoAA(packed);
2203afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            size_t offsetToRestore = reader->readInt();
2213afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
222ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->clipRRect(rrect, regionOp, doAA);
223ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            if (canvas->isClipEmpty() && offsetToRestore) {
2243afef1f75f710b8f183113cdc5188416f7d01f28robertphillips                reader->setOffset(offsetToRestore);
225ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            }
226ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
227ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case PUSH_CULL: {
2283afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkRect& cullRect = reader->skipT<SkRect>();
2293afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            size_t offsetToRestore = reader->readInt();
230ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            if (offsetToRestore && canvas->quickReject(cullRect)) {
2313afef1f75f710b8f183113cdc5188416f7d01f28robertphillips                reader->setOffset(offsetToRestore);
232ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            } else {
233ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips                canvas->pushCull(cullRect);
234ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            }
235ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
236ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case POP_CULL:
237ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->popCull();
238ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            break;
239ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case CONCAT: {
240ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkMatrix matrix;
2413afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            reader->readMatrix(&matrix);
242ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->concat(matrix);
243ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            break;
244ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        }
245ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_BITMAP: {
246ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint* paint = fPictureData->getPaint(reader);
247eeb1f15891ee9f96f2c5d6e1c3d5a656208f3760mtklein            const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
2483afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkPoint& loc = reader->skipT<SkPoint>();
249ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawBitmap(bitmap, loc.fX, loc.fY, paint);
250ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
251ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_BITMAP_RECT_TO_RECT: {
252ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint* paint = fPictureData->getPaint(reader);
253eeb1f15891ee9f96f2c5d6e1c3d5a656208f3760mtklein            const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
254ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkRect* src = get_rect_ptr(reader);   // may be null
2553afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkRect& dst = reader->skipT<SkRect>();     // required
256ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkCanvas::DrawBitmapRectFlags flags;
2573afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            flags = (SkCanvas::DrawBitmapRectFlags) reader->readInt();
258ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawBitmapRectToRect(bitmap, src, dst, paint, flags);
259ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
260ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_BITMAP_MATRIX: {
261ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint* paint = fPictureData->getPaint(reader);
262eeb1f15891ee9f96f2c5d6e1c3d5a656208f3760mtklein            const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
263ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkMatrix matrix;
2643afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            reader->readMatrix(&matrix);
265ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawBitmapMatrix(bitmap, matrix, paint);
266ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
267ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_BITMAP_NINE: {
268ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint* paint = fPictureData->getPaint(reader);
269eeb1f15891ee9f96f2c5d6e1c3d5a656208f3760mtklein            const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
2703afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkIRect& src = reader->skipT<SkIRect>();
2713afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkRect& dst = reader->skipT<SkRect>();
272ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawBitmapNine(bitmap, src, dst, paint);
273ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
274ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_CLEAR:
2753afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            canvas->clear(reader->readInt());
276ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            break;
277ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_DATA: {
2783afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            size_t length = reader->readInt();
2793afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            canvas->drawData(reader->skip(length), length);
280ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            // skip handles padding the read out to a multiple of 4
281ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
282ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_DRRECT: {
283ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
284ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkRRect outer, inner;
2853afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            reader->readRRect(&outer);
2863afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            reader->readRRect(&inner);
287ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawDRRect(outer, inner, paint);
288ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
289ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case BEGIN_COMMENT_GROUP: {
2903afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const char* desc = reader->readString();
291ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->beginCommentGroup(desc);
292ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
293ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case COMMENT: {
2943afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const char* kywd = reader->readString();
2953afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const char* value = reader->readString();
296ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->addComment(kywd, value);
297ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
298ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case END_COMMENT_GROUP: {
299ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->endCommentGroup();
300ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
301ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_OVAL: {
302ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
3033afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            canvas->drawOval(reader->skipT<SkRect>(), paint);
304ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
305ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_PAINT:
306ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawPaint(*fPictureData->getPaint(reader));
307ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            break;
308963137b75c0a1fe91f35e9826742f36309f5e65ddandov        case DRAW_PATCH: {
309963137b75c0a1fe91f35e9826742f36309f5e65ddandov            const SkPaint& paint = *fPictureData->getPaint(reader);
310533eb782edaa0b6fece6166d3001edf72ec39f11mtklein
311b3c9d1c33caf325aada244204215eb790c228c12dandov            const SkPoint* cubics = (const SkPoint*)reader->skip(SkPatchUtils::kNumCtrlPts *
312b3c9d1c33caf325aada244204215eb790c228c12dandov                                                                 sizeof(SkPoint));
313b3c9d1c33caf325aada244204215eb790c228c12dandov            uint32_t flag = reader->readInt();
314b3c9d1c33caf325aada244204215eb790c228c12dandov            const SkColor* colors = NULL;
315b3c9d1c33caf325aada244204215eb790c228c12dandov            if (flag & DRAW_VERTICES_HAS_COLORS) {
316b3c9d1c33caf325aada244204215eb790c228c12dandov                colors = (const SkColor*)reader->skip(SkPatchUtils::kNumCorners * sizeof(SkColor));
317b3c9d1c33caf325aada244204215eb790c228c12dandov            }
318b3c9d1c33caf325aada244204215eb790c228c12dandov            const SkPoint* texCoords = NULL;
319b3c9d1c33caf325aada244204215eb790c228c12dandov            if (flag & DRAW_VERTICES_HAS_TEXS) {
320b3c9d1c33caf325aada244204215eb790c228c12dandov                texCoords = (const SkPoint*)reader->skip(SkPatchUtils::kNumCorners *
321b3c9d1c33caf325aada244204215eb790c228c12dandov                                                         sizeof(SkPoint));
322b3c9d1c33caf325aada244204215eb790c228c12dandov            }
323b3c9d1c33caf325aada244204215eb790c228c12dandov            SkAutoTUnref<SkXfermode> xfer;
324b3c9d1c33caf325aada244204215eb790c228c12dandov            if (flag & DRAW_VERTICES_HAS_XFER) {
325b3c9d1c33caf325aada244204215eb790c228c12dandov                int mode = reader->readInt();
326b3c9d1c33caf325aada244204215eb790c228c12dandov                if (mode < 0 || mode > SkXfermode::kLastMode) {
327b3c9d1c33caf325aada244204215eb790c228c12dandov                    mode = SkXfermode::kModulate_Mode;
328b3c9d1c33caf325aada244204215eb790c228c12dandov                }
329b3c9d1c33caf325aada244204215eb790c228c12dandov                xfer.reset(SkXfermode::Create((SkXfermode::Mode)mode));
330b3c9d1c33caf325aada244204215eb790c228c12dandov            }
331b3c9d1c33caf325aada244204215eb790c228c12dandov            canvas->drawPatch(cubics, colors, texCoords, xfer, paint);
332963137b75c0a1fe91f35e9826742f36309f5e65ddandov        } break;
333ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_PATH: {
334ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
335ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawPath(fPictureData->getPath(reader), paint);
336ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
337ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_PICTURE:
338ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawPicture(fPictureData->getPicture(reader));
339ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            break;
340d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        case DRAW_PICTURE_MATRIX_PAINT: {
3419f49cfdbf6493b953775890d7f9c97a1dce0d341fmalita            const SkPaint* paint = fPictureData->getPaint(reader);
342d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed            SkMatrix matrix;
343d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed            reader->readMatrix(&matrix);
3449f49cfdbf6493b953775890d7f9c97a1dce0d341fmalita            const SkPicture* pic = fPictureData->getPicture(reader);
345d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed            canvas->drawPicture(pic, &matrix, paint);
346d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        } break;
347ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_POINTS: {
348ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
3493afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkCanvas::PointMode mode = (SkCanvas::PointMode)reader->readInt();
3503afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            size_t count = reader->readInt();
3513afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkPoint* pts = (const SkPoint*)reader->skip(sizeof(SkPoint)* count);
352ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawPoints(mode, count, pts, paint);
353ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
354ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_POS_TEXT: {
355ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
3563afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            TextContainer text;
3573afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            get_text(reader, &text);
3583afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            size_t points = reader->readInt();
3593afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkPoint* pos = (const SkPoint*)reader->skip(points * sizeof(SkPoint));
360ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawPosText(text.text(), text.length(), pos, paint);
361ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
362ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_POS_TEXT_TOP_BOTTOM: {
363ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
3643afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            TextContainer text;
3653afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            get_text(reader, &text);
3663afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            size_t points = reader->readInt();
3673afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkPoint* pos = (const SkPoint*)reader->skip(points * sizeof(SkPoint));
3683afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkScalar top = reader->readScalar();
3693afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkScalar bottom = reader->readScalar();
370ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            if (!canvas->quickRejectY(top, bottom)) {
371ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips                canvas->drawPosText(text.text(), text.length(), pos, paint);
372ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            }
373ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
374ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_POS_TEXT_H: {
375ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
3763afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            TextContainer text;
3773afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            get_text(reader, &text);
3783afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            size_t xCount = reader->readInt();
3793afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkScalar constY = reader->readScalar();
3803afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkScalar* xpos = (const SkScalar*)reader->skip(xCount * sizeof(SkScalar));
381ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawPosTextH(text.text(), text.length(), xpos, constY, paint);
382ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
383ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_POS_TEXT_H_TOP_BOTTOM: {
384ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
3853afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            TextContainer text;
3863afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            get_text(reader, &text);
3873afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            size_t xCount = reader->readInt();
3883afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkScalar* xpos = (const SkScalar*)reader->skip((3 + xCount) * sizeof(SkScalar));
389ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkScalar top = *xpos++;
390ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkScalar bottom = *xpos++;
391ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkScalar constY = *xpos++;
392ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            if (!canvas->quickRejectY(top, bottom)) {
393ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips                canvas->drawPosTextH(text.text(), text.length(), xpos, constY, paint);
394ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            }
395ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
396ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_RECT: {
397ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
3983afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            canvas->drawRect(reader->skipT<SkRect>(), paint);
399ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
400ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_RRECT: {
401ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
402ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkRRect rrect;
4033afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            reader->readRRect(&rrect);
404ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawRRect(rrect, paint);
405ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
406ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_SPRITE: {
407ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint* paint = fPictureData->getPaint(reader);
408eeb1f15891ee9f96f2c5d6e1c3d5a656208f3760mtklein            const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
4093afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            int left = reader->readInt();
4103afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            int top = reader->readInt();
411ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawSprite(bitmap, left, top, paint);
412ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
413ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_TEXT: {
414ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
4153afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            TextContainer text;
4163afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            get_text(reader, &text);
4173afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkScalar x = reader->readScalar();
4183afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkScalar y = reader->readScalar();
419ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawText(text.text(), text.length(), x, y, paint);
420ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
421b7425173f96e93b090787e2386ba5f022b6c2869fmalita        case DRAW_TEXT_BLOB: {
422b7425173f96e93b090787e2386ba5f022b6c2869fmalita            const SkPaint& paint = *fPictureData->getPaint(reader);
423b7425173f96e93b090787e2386ba5f022b6c2869fmalita            const SkTextBlob* blob = fPictureData->getTextBlob(reader);
424b7425173f96e93b090787e2386ba5f022b6c2869fmalita            SkScalar x = reader->readScalar();
425b7425173f96e93b090787e2386ba5f022b6c2869fmalita            SkScalar y = reader->readScalar();
426b7425173f96e93b090787e2386ba5f022b6c2869fmalita            canvas->drawTextBlob(blob, x, y, paint);
427b7425173f96e93b090787e2386ba5f022b6c2869fmalita        } break;
428ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_TEXT_TOP_BOTTOM: {
429ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
4303afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            TextContainer text;
4313afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            get_text(reader, &text);
4323afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkScalar* ptr = (const SkScalar*)reader->skip(4 * sizeof(SkScalar));
433ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            // ptr[0] == x
434ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            // ptr[1] == y
435ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            // ptr[2] == top
436ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            // ptr[3] == bottom
437ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            if (!canvas->quickRejectY(ptr[2], ptr[3])) {
438ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips                canvas->drawText(text.text(), text.length(), ptr[0], ptr[1], paint);
439ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            }
440ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
441ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_TEXT_ON_PATH: {
442ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
4433afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            TextContainer text;
4443afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            get_text(reader, &text);
445ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPath& path = fPictureData->getPath(reader);
446ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkMatrix matrix;
4473afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            reader->readMatrix(&matrix);
448ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawTextOnPath(text.text(), text.length(), path, &matrix, paint);
449ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
450ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_VERTICES: {
451ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkAutoTUnref<SkXfermode> xfer;
452ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
4533afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            DrawVertexFlags flags = (DrawVertexFlags)reader->readInt();
4543afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkCanvas::VertexMode vmode = (SkCanvas::VertexMode)reader->readInt();
4553afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            int vCount = reader->readInt();
4563afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkPoint* verts = (const SkPoint*)reader->skip(vCount * sizeof(SkPoint));
457ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPoint* texs = NULL;
458ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkColor* colors = NULL;
459ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const uint16_t* indices = NULL;
460ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            int iCount = 0;
461ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            if (flags & DRAW_VERTICES_HAS_TEXS) {
4623afef1f75f710b8f183113cdc5188416f7d01f28robertphillips                texs = (const SkPoint*)reader->skip(vCount * sizeof(SkPoint));
463ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            }
464ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            if (flags & DRAW_VERTICES_HAS_COLORS) {
4653afef1f75f710b8f183113cdc5188416f7d01f28robertphillips                colors = (const SkColor*)reader->skip(vCount * sizeof(SkColor));
466ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            }
467ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            if (flags & DRAW_VERTICES_HAS_INDICES) {
4683afef1f75f710b8f183113cdc5188416f7d01f28robertphillips                iCount = reader->readInt();
4693afef1f75f710b8f183113cdc5188416f7d01f28robertphillips                indices = (const uint16_t*)reader->skip(iCount * sizeof(uint16_t));
470ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            }
471ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            if (flags & DRAW_VERTICES_HAS_XFER) {
4723afef1f75f710b8f183113cdc5188416f7d01f28robertphillips                int mode = reader->readInt();
473ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips                if (mode < 0 || mode > SkXfermode::kLastMode) {
474ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips                    mode = SkXfermode::kModulate_Mode;
475ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips                }
476ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips                xfer.reset(SkXfermode::Create((SkXfermode::Mode)mode));
477ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            }
478ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawVertices(vmode, vCount, verts, texs, colors, xfer, indices, iCount, paint);
479ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
480ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case RESTORE:
481ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->restore();
482ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            break;
483ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case ROTATE:
4843afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            canvas->rotate(reader->readScalar());
485ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            break;
486ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case SAVE:
487ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            // SKPs with version < 29 also store a SaveFlags param.
488ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            if (size > 4) {
489ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips                SkASSERT(8 == size);
4903afef1f75f710b8f183113cdc5188416f7d01f28robertphillips                reader->readInt();
491ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            }
492ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->save();
493ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            break;
494ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case SAVE_LAYER: {
495ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkRect* boundsPtr = get_rect_ptr(reader);
496ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint* paint = fPictureData->getPaint(reader);
4973afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            canvas->saveLayer(boundsPtr, paint, (SkCanvas::SaveFlags) reader->readInt());
498ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
499ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case SCALE: {
5003afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkScalar sx = reader->readScalar();
5013afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkScalar sy = reader->readScalar();
502ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->scale(sx, sy);
503ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
504ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case SET_MATRIX: {
505ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkMatrix matrix;
5063afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            reader->readMatrix(&matrix);
507ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            matrix.postConcat(initialMatrix);
508ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->setMatrix(matrix);
509ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
510ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case SKEW: {
5113afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkScalar sx = reader->readScalar();
5123afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkScalar sy = reader->readScalar();
513ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->skew(sx, sy);
514ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
515ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case TRANSLATE: {
5163afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkScalar dx = reader->readScalar();
5173afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkScalar dy = reader->readScalar();
518ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->translate(dx, dy);
519ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
520ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        default:
521ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkASSERT(0);
522ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    }
523ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips}
524ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips
525