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 "SkReader32.h"
14b7425173f96e93b090787e2386ba5f022b6c2869fmalita#include "SkTextBlob.h"
15ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips#include "SkTDArray.h"
16ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips#include "SkTypes.h"
17ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips
18ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips/*
191ad00e4b245d464c16ba78bdaa377281f29972cdrobertphillips * Read the next op code and chunk size from 'reader'. The returned size
201ad00e4b245d464c16ba78bdaa377281f29972cdrobertphillips * is the entire size of the chunk (including the opcode). Thus, the
211ad00e4b245d464c16ba78bdaa377281f29972cdrobertphillips * offset just prior to calling ReadOpAndSize + 'size' is the offset
221ad00e4b245d464c16ba78bdaa377281f29972cdrobertphillips * to the next chunk's op code. This also means that the size of a chunk
231ad00e4b245d464c16ba78bdaa377281f29972cdrobertphillips * with no arguments (just an opcode) will be 4.
241ad00e4b245d464c16ba78bdaa377281f29972cdrobertphillips */
251ad00e4b245d464c16ba78bdaa377281f29972cdrobertphillipsDrawType SkPicturePlayback::ReadOpAndSize(SkReader32* reader, uint32_t* size) {
26ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    uint32_t temp = reader->readInt();
27ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    uint32_t op;
28ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    if (((uint8_t)temp) == temp) {
29ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        // old skp file - no size information
30ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        op = temp;
31ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        *size = 0;
32ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    } else {
33ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        UNPACK_8_24(temp, op, *size);
34ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        if (MASK_24 == *size) {
35ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            *size = reader->readInt();
36ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        }
37ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    }
38ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    return (DrawType)op;
39ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips}
40ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips
41ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips
423afef1f75f710b8f183113cdc5188416f7d01f28robertphillipsstatic const SkRect* get_rect_ptr(SkReader32* reader) {
433afef1f75f710b8f183113cdc5188416f7d01f28robertphillips    if (reader->readBool()) {
443afef1f75f710b8f183113cdc5188416f7d01f28robertphillips        return &reader->skipT<SkRect>();
45ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    } else {
46ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        return NULL;
47ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    }
48ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips}
49ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips
50ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillipsclass TextContainer {
51ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillipspublic:
52ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    size_t length() { return fByteLength; }
53ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    const void* text() { return (const void*)fText; }
54ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    size_t fByteLength;
55ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    const char* fText;
56ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips};
57ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips
58ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillipsvoid get_text(SkReader32* reader, TextContainer* text) {
59ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    size_t length = text->fByteLength = reader->readInt();
60ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    text->fText = (const char*)reader->skip(length);
61ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips}
62ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips
63eeb1f15891ee9f96f2c5d6e1c3d5a656208f3760mtklein// FIXME: SkBitmaps are stateful, so we need to copy them to play back in multiple threads.
64eeb1f15891ee9f96f2c5d6e1c3d5a656208f3760mtkleinstatic SkBitmap shallow_copy(const SkBitmap& bitmap) {
65eeb1f15891ee9f96f2c5d6e1c3d5a656208f3760mtklein    return bitmap;
66eeb1f15891ee9f96f2c5d6e1c3d5a656208f3760mtklein}
67eeb1f15891ee9f96f2c5d6e1c3d5a656208f3760mtklein
68783fe16b8ed1cd1cff34eacc33296874a32f293brobertphillipsvoid SkPicturePlayback::draw(SkCanvas* canvas, SkPicture::AbortCallback* callback) {
69ec66e6264de5110802c3d9927380d913242c9d5frobertphillips    AutoResetOpID aroi(this);
70ec66e6264de5110802c3d9927380d913242c9d5frobertphillips    SkASSERT(0 == fCurOffset);
71ec66e6264de5110802c3d9927380d913242c9d5frobertphillips
72ec66e6264de5110802c3d9927380d913242c9d5frobertphillips    SkReader32 reader(fPictureData->opData()->bytes(), fPictureData->opData()->size());
73ec66e6264de5110802c3d9927380d913242c9d5frobertphillips
74ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    // Record this, so we can concat w/ it if we encounter a setMatrix()
75ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    SkMatrix initialMatrix = canvas->getTotalMatrix();
76ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips
77ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    SkAutoCanvasRestore acr(canvas, false);
78ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips
79ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    while (!reader.eof()) {
80783fe16b8ed1cd1cff34eacc33296874a32f293brobertphillips        if (callback && callback->abort()) {
81ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            return;
82ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        }
83ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips
84ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        fCurOffset = reader.offset();
85ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        uint32_t size;
861ad00e4b245d464c16ba78bdaa377281f29972cdrobertphillips        DrawType op = ReadOpAndSize(&reader, &size);
87ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips
883afef1f75f710b8f183113cdc5188416f7d01f28robertphillips        this->handleOp(&reader, op, size, canvas, initialMatrix);
893afef1f75f710b8f183113cdc5188416f7d01f28robertphillips    }
903afef1f75f710b8f183113cdc5188416f7d01f28robertphillips}
913afef1f75f710b8f183113cdc5188416f7d01f28robertphillips
92533eb782edaa0b6fece6166d3001edf72ec39f11mtkleinvoid SkPicturePlayback::handleOp(SkReader32* reader,
93533eb782edaa0b6fece6166d3001edf72ec39f11mtklein                                 DrawType op,
94533eb782edaa0b6fece6166d3001edf72ec39f11mtklein                                 uint32_t size,
953afef1f75f710b8f183113cdc5188416f7d01f28robertphillips                                 SkCanvas* canvas,
963afef1f75f710b8f183113cdc5188416f7d01f28robertphillips                                 const SkMatrix& initialMatrix) {
973afef1f75f710b8f183113cdc5188416f7d01f28robertphillips    switch (op) {
9846616af01b412ea984a516fda1ed8ec08e689f29mtklein        case NOOP: {
9946616af01b412ea984a516fda1ed8ec08e689f29mtklein            SkASSERT(size >= 4);
10046616af01b412ea984a516fda1ed8ec08e689f29mtklein            reader->skip(size - 4);
10146616af01b412ea984a516fda1ed8ec08e689f29mtklein        } break;
102ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case CLIP_PATH: {
103ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPath& path = fPictureData->getPath(reader);
1043afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            uint32_t packed = reader->readInt();
105ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
106ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            bool doAA = ClipParams_unpackDoAA(packed);
1073afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            size_t offsetToRestore = reader->readInt();
1083afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
109ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->clipPath(path, regionOp, doAA);
110ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            if (canvas->isClipEmpty() && offsetToRestore) {
1113afef1f75f710b8f183113cdc5188416f7d01f28robertphillips                reader->setOffset(offsetToRestore);
112ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            }
113ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
114ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case CLIP_REGION: {
115ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkRegion region;
1163afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            reader->readRegion(&region);
1173afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            uint32_t packed = reader->readInt();
118ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
1193afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            size_t offsetToRestore = reader->readInt();
1203afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
121ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->clipRegion(region, regionOp);
122ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            if (canvas->isClipEmpty() && offsetToRestore) {
1233afef1f75f710b8f183113cdc5188416f7d01f28robertphillips                reader->setOffset(offsetToRestore);
124ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            }
125ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
126ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case CLIP_RECT: {
1273afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkRect& rect = reader->skipT<SkRect>();
1283afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            uint32_t packed = reader->readInt();
129ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
130ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            bool doAA = ClipParams_unpackDoAA(packed);
1313afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            size_t offsetToRestore = reader->readInt();
1323afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
133ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->clipRect(rect, regionOp, doAA);
134ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            if (canvas->isClipEmpty() && offsetToRestore) {
1353afef1f75f710b8f183113cdc5188416f7d01f28robertphillips                reader->setOffset(offsetToRestore);
136ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            }
137ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
138ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case CLIP_RRECT: {
139ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkRRect rrect;
1403afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            reader->readRRect(&rrect);
1413afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            uint32_t packed = reader->readInt();
142ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
143ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            bool doAA = ClipParams_unpackDoAA(packed);
1443afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            size_t offsetToRestore = reader->readInt();
1453afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
146ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->clipRRect(rrect, regionOp, doAA);
147ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            if (canvas->isClipEmpty() && offsetToRestore) {
1483afef1f75f710b8f183113cdc5188416f7d01f28robertphillips                reader->setOffset(offsetToRestore);
149ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            }
150ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
151f0f14113431ace669f278fdd97b50950f2cf4c80mtklein        case PUSH_CULL: break;  // Deprecated, safe to ignore both push and pop.
152f0f14113431ace669f278fdd97b50950f2cf4c80mtklein        case POP_CULL:  break;
153ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case CONCAT: {
154ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkMatrix matrix;
1553afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            reader->readMatrix(&matrix);
156ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->concat(matrix);
157ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            break;
158ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        }
159ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_BITMAP: {
160ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint* paint = fPictureData->getPaint(reader);
161eeb1f15891ee9f96f2c5d6e1c3d5a656208f3760mtklein            const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
1623afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkPoint& loc = reader->skipT<SkPoint>();
163ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawBitmap(bitmap, loc.fX, loc.fY, paint);
164ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
165ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_BITMAP_RECT_TO_RECT: {
166ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint* paint = fPictureData->getPaint(reader);
167eeb1f15891ee9f96f2c5d6e1c3d5a656208f3760mtklein            const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
168ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkRect* src = get_rect_ptr(reader);   // may be null
1693afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkRect& dst = reader->skipT<SkRect>();     // required
170ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkCanvas::DrawBitmapRectFlags flags;
1713afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            flags = (SkCanvas::DrawBitmapRectFlags) reader->readInt();
172ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawBitmapRectToRect(bitmap, src, dst, paint, flags);
173ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
174ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_BITMAP_MATRIX: {
175ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint* paint = fPictureData->getPaint(reader);
176eeb1f15891ee9f96f2c5d6e1c3d5a656208f3760mtklein            const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
177ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkMatrix matrix;
1783afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            reader->readMatrix(&matrix);
179c54d8db4d169ea5f2af2a9a2349df007bd428475Florin Malita
180c54d8db4d169ea5f2af2a9a2349df007bd428475Florin Malita            SkAutoCanvasRestore acr(canvas, true);
181c54d8db4d169ea5f2af2a9a2349df007bd428475Florin Malita            canvas->concat(matrix);
182c54d8db4d169ea5f2af2a9a2349df007bd428475Florin Malita            canvas->drawBitmap(bitmap, 0, 0, paint);
183ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
184ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_BITMAP_NINE: {
185ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint* paint = fPictureData->getPaint(reader);
186eeb1f15891ee9f96f2c5d6e1c3d5a656208f3760mtklein            const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
1873afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkIRect& src = reader->skipT<SkIRect>();
1883afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkRect& dst = reader->skipT<SkRect>();
189ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawBitmapNine(bitmap, src, dst, paint);
190ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
191ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_CLEAR:
1923afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            canvas->clear(reader->readInt());
193ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            break;
194ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_DATA: {
195c4fda92f45b9649f233a5b8636618a6431aa59cbreed            // This opcode is now dead, just need to skip it for backwards compatibility
1963afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            size_t length = reader->readInt();
197c4fda92f45b9649f233a5b8636618a6431aa59cbreed            (void)reader->skip(length);
198ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            // skip handles padding the read out to a multiple of 4
199ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
200ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_DRRECT: {
201ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
202ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkRRect outer, inner;
2033afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            reader->readRRect(&outer);
2043afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            reader->readRRect(&inner);
205ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawDRRect(outer, inner, paint);
206ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
207ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case BEGIN_COMMENT_GROUP: {
2083afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const char* desc = reader->readString();
209ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->beginCommentGroup(desc);
210ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
211ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case COMMENT: {
2123afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const char* kywd = reader->readString();
2133afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const char* value = reader->readString();
214ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->addComment(kywd, value);
215ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
216ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case END_COMMENT_GROUP: {
217ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->endCommentGroup();
218ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
219ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_OVAL: {
220ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
2213afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            canvas->drawOval(reader->skipT<SkRect>(), paint);
222ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
223ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_PAINT:
224ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawPaint(*fPictureData->getPaint(reader));
225ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            break;
226963137b75c0a1fe91f35e9826742f36309f5e65ddandov        case DRAW_PATCH: {
227963137b75c0a1fe91f35e9826742f36309f5e65ddandov            const SkPaint& paint = *fPictureData->getPaint(reader);
228533eb782edaa0b6fece6166d3001edf72ec39f11mtklein
229b3c9d1c33caf325aada244204215eb790c228c12dandov            const SkPoint* cubics = (const SkPoint*)reader->skip(SkPatchUtils::kNumCtrlPts *
230b3c9d1c33caf325aada244204215eb790c228c12dandov                                                                 sizeof(SkPoint));
231b3c9d1c33caf325aada244204215eb790c228c12dandov            uint32_t flag = reader->readInt();
232b3c9d1c33caf325aada244204215eb790c228c12dandov            const SkColor* colors = NULL;
233b3c9d1c33caf325aada244204215eb790c228c12dandov            if (flag & DRAW_VERTICES_HAS_COLORS) {
234b3c9d1c33caf325aada244204215eb790c228c12dandov                colors = (const SkColor*)reader->skip(SkPatchUtils::kNumCorners * sizeof(SkColor));
235b3c9d1c33caf325aada244204215eb790c228c12dandov            }
236b3c9d1c33caf325aada244204215eb790c228c12dandov            const SkPoint* texCoords = NULL;
237b3c9d1c33caf325aada244204215eb790c228c12dandov            if (flag & DRAW_VERTICES_HAS_TEXS) {
238b3c9d1c33caf325aada244204215eb790c228c12dandov                texCoords = (const SkPoint*)reader->skip(SkPatchUtils::kNumCorners *
239b3c9d1c33caf325aada244204215eb790c228c12dandov                                                         sizeof(SkPoint));
240b3c9d1c33caf325aada244204215eb790c228c12dandov            }
241b3c9d1c33caf325aada244204215eb790c228c12dandov            SkAutoTUnref<SkXfermode> xfer;
242b3c9d1c33caf325aada244204215eb790c228c12dandov            if (flag & DRAW_VERTICES_HAS_XFER) {
243b3c9d1c33caf325aada244204215eb790c228c12dandov                int mode = reader->readInt();
244b3c9d1c33caf325aada244204215eb790c228c12dandov                if (mode < 0 || mode > SkXfermode::kLastMode) {
245b3c9d1c33caf325aada244204215eb790c228c12dandov                    mode = SkXfermode::kModulate_Mode;
246b3c9d1c33caf325aada244204215eb790c228c12dandov                }
247b3c9d1c33caf325aada244204215eb790c228c12dandov                xfer.reset(SkXfermode::Create((SkXfermode::Mode)mode));
248b3c9d1c33caf325aada244204215eb790c228c12dandov            }
249b3c9d1c33caf325aada244204215eb790c228c12dandov            canvas->drawPatch(cubics, colors, texCoords, xfer, paint);
250963137b75c0a1fe91f35e9826742f36309f5e65ddandov        } break;
251ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_PATH: {
252ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
253ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawPath(fPictureData->getPath(reader), paint);
254ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
255ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_PICTURE:
256ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawPicture(fPictureData->getPicture(reader));
257ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            break;
258d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        case DRAW_PICTURE_MATRIX_PAINT: {
2599f49cfdbf6493b953775890d7f9c97a1dce0d341fmalita            const SkPaint* paint = fPictureData->getPaint(reader);
260d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed            SkMatrix matrix;
261d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed            reader->readMatrix(&matrix);
2629f49cfdbf6493b953775890d7f9c97a1dce0d341fmalita            const SkPicture* pic = fPictureData->getPicture(reader);
263d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed            canvas->drawPicture(pic, &matrix, paint);
264d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        } break;
265ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_POINTS: {
266ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
2673afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkCanvas::PointMode mode = (SkCanvas::PointMode)reader->readInt();
2683afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            size_t count = reader->readInt();
2693afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkPoint* pts = (const SkPoint*)reader->skip(sizeof(SkPoint)* count);
270ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawPoints(mode, count, pts, paint);
271ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
272ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_POS_TEXT: {
273ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
2743afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            TextContainer text;
2753afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            get_text(reader, &text);
2763afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            size_t points = reader->readInt();
2773afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkPoint* pos = (const SkPoint*)reader->skip(points * sizeof(SkPoint));
278ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawPosText(text.text(), text.length(), pos, paint);
279ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
280ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_POS_TEXT_TOP_BOTTOM: {
281ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
2823afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            TextContainer text;
2833afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            get_text(reader, &text);
2843afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            size_t points = reader->readInt();
2853afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkPoint* pos = (const SkPoint*)reader->skip(points * sizeof(SkPoint));
2863afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkScalar top = reader->readScalar();
2873afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkScalar bottom = reader->readScalar();
288ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            if (!canvas->quickRejectY(top, bottom)) {
289ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips                canvas->drawPosText(text.text(), text.length(), pos, paint);
290ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            }
291ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
292ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_POS_TEXT_H: {
293ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
2943afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            TextContainer text;
2953afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            get_text(reader, &text);
2963afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            size_t xCount = reader->readInt();
2973afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkScalar constY = reader->readScalar();
2983afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkScalar* xpos = (const SkScalar*)reader->skip(xCount * sizeof(SkScalar));
299ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawPosTextH(text.text(), text.length(), xpos, constY, paint);
300ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
301ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_POS_TEXT_H_TOP_BOTTOM: {
302ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
3033afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            TextContainer text;
3043afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            get_text(reader, &text);
3053afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            size_t xCount = reader->readInt();
3063afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkScalar* xpos = (const SkScalar*)reader->skip((3 + xCount) * sizeof(SkScalar));
307ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkScalar top = *xpos++;
308ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkScalar bottom = *xpos++;
309ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkScalar constY = *xpos++;
310ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            if (!canvas->quickRejectY(top, bottom)) {
311ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips                canvas->drawPosTextH(text.text(), text.length(), xpos, constY, paint);
312ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            }
313ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
314ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_RECT: {
315ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
3163afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            canvas->drawRect(reader->skipT<SkRect>(), paint);
317ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
318ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_RRECT: {
319ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
320ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkRRect rrect;
3213afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            reader->readRRect(&rrect);
322ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawRRect(rrect, paint);
323ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
324ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_SPRITE: {
325ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint* paint = fPictureData->getPaint(reader);
326eeb1f15891ee9f96f2c5d6e1c3d5a656208f3760mtklein            const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
3273afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            int left = reader->readInt();
3283afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            int top = reader->readInt();
329ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawSprite(bitmap, left, top, paint);
330ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
331ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_TEXT: {
332ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
3333afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            TextContainer text;
3343afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            get_text(reader, &text);
3353afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkScalar x = reader->readScalar();
3363afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkScalar y = reader->readScalar();
337ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawText(text.text(), text.length(), x, y, paint);
338ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
339b7425173f96e93b090787e2386ba5f022b6c2869fmalita        case DRAW_TEXT_BLOB: {
340b7425173f96e93b090787e2386ba5f022b6c2869fmalita            const SkPaint& paint = *fPictureData->getPaint(reader);
341b7425173f96e93b090787e2386ba5f022b6c2869fmalita            const SkTextBlob* blob = fPictureData->getTextBlob(reader);
342b7425173f96e93b090787e2386ba5f022b6c2869fmalita            SkScalar x = reader->readScalar();
343b7425173f96e93b090787e2386ba5f022b6c2869fmalita            SkScalar y = reader->readScalar();
344b7425173f96e93b090787e2386ba5f022b6c2869fmalita            canvas->drawTextBlob(blob, x, y, paint);
345b7425173f96e93b090787e2386ba5f022b6c2869fmalita        } break;
346ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_TEXT_TOP_BOTTOM: {
347ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
3483afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            TextContainer text;
3493afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            get_text(reader, &text);
3503afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkScalar* ptr = (const SkScalar*)reader->skip(4 * sizeof(SkScalar));
351ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            // ptr[0] == x
352ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            // ptr[1] == y
353ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            // ptr[2] == top
354ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            // ptr[3] == bottom
355ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            if (!canvas->quickRejectY(ptr[2], ptr[3])) {
356ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips                canvas->drawText(text.text(), text.length(), ptr[0], ptr[1], paint);
357ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            }
358ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
359ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_TEXT_ON_PATH: {
360ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
3613afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            TextContainer text;
3623afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            get_text(reader, &text);
363ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPath& path = fPictureData->getPath(reader);
364ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkMatrix matrix;
3653afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            reader->readMatrix(&matrix);
366ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawTextOnPath(text.text(), text.length(), path, &matrix, paint);
367ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
368ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case DRAW_VERTICES: {
369ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkAutoTUnref<SkXfermode> xfer;
370ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint& paint = *fPictureData->getPaint(reader);
3713afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            DrawVertexFlags flags = (DrawVertexFlags)reader->readInt();
3723afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkCanvas::VertexMode vmode = (SkCanvas::VertexMode)reader->readInt();
3733afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            int vCount = reader->readInt();
3743afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            const SkPoint* verts = (const SkPoint*)reader->skip(vCount * sizeof(SkPoint));
375ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPoint* texs = NULL;
376ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkColor* colors = NULL;
377ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const uint16_t* indices = NULL;
378ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            int iCount = 0;
379ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            if (flags & DRAW_VERTICES_HAS_TEXS) {
3803afef1f75f710b8f183113cdc5188416f7d01f28robertphillips                texs = (const SkPoint*)reader->skip(vCount * sizeof(SkPoint));
381ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            }
382ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            if (flags & DRAW_VERTICES_HAS_COLORS) {
3833afef1f75f710b8f183113cdc5188416f7d01f28robertphillips                colors = (const SkColor*)reader->skip(vCount * sizeof(SkColor));
384ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            }
385ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            if (flags & DRAW_VERTICES_HAS_INDICES) {
3863afef1f75f710b8f183113cdc5188416f7d01f28robertphillips                iCount = reader->readInt();
3873afef1f75f710b8f183113cdc5188416f7d01f28robertphillips                indices = (const uint16_t*)reader->skip(iCount * sizeof(uint16_t));
388ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            }
389ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            if (flags & DRAW_VERTICES_HAS_XFER) {
3903afef1f75f710b8f183113cdc5188416f7d01f28robertphillips                int mode = reader->readInt();
391ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips                if (mode < 0 || mode > SkXfermode::kLastMode) {
392ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips                    mode = SkXfermode::kModulate_Mode;
393ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips                }
394ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips                xfer.reset(SkXfermode::Create((SkXfermode::Mode)mode));
395ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            }
396ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->drawVertices(vmode, vCount, verts, texs, colors, xfer, indices, iCount, paint);
397ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
398ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case RESTORE:
399ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->restore();
400ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            break;
401ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case ROTATE:
4023afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            canvas->rotate(reader->readScalar());
403ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            break;
404ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case SAVE:
405ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            // SKPs with version < 29 also store a SaveFlags param.
406ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            if (size > 4) {
407ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips                SkASSERT(8 == size);
4083afef1f75f710b8f183113cdc5188416f7d01f28robertphillips                reader->readInt();
409ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            }
410ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->save();
411ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            break;
412ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case SAVE_LAYER: {
413ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkRect* boundsPtr = get_rect_ptr(reader);
414ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            const SkPaint* paint = fPictureData->getPaint(reader);
4153afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            canvas->saveLayer(boundsPtr, paint, (SkCanvas::SaveFlags) reader->readInt());
416ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
417ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case SCALE: {
4183afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkScalar sx = reader->readScalar();
4193afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkScalar sy = reader->readScalar();
420ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->scale(sx, sy);
421ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
422ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case SET_MATRIX: {
423ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            SkMatrix matrix;
4243afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            reader->readMatrix(&matrix);
425ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            matrix.postConcat(initialMatrix);
426ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->setMatrix(matrix);
427ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
428ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case SKEW: {
4293afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkScalar sx = reader->readScalar();
4303afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkScalar sy = reader->readScalar();
431ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->skew(sx, sy);
432ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
433ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        case TRANSLATE: {
4343afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkScalar dx = reader->readScalar();
4353afef1f75f710b8f183113cdc5188416f7d01f28robertphillips            SkScalar dy = reader->readScalar();
436ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips            canvas->translate(dx, dy);
437ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        } break;
438ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips        default:
43946616af01b412ea984a516fda1ed8ec08e689f29mtklein            SkASSERTF(false, "Unknown draw type: %d", op);
440ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips    }
441ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips}
442ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips
443