1/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkCanvas.h"
9#include "SkPatchUtils.h"
10#include "SkPictureData.h"
11#include "SkPicturePlayback.h"
12#include "SkPictureRecord.h"
13#include "SkReadBuffer.h"
14#include "SkRSXform.h"
15#include "SkTextBlob.h"
16#include "SkTDArray.h"
17#include "SkTypes.h"
18
19// matches old SkCanvas::SaveFlags
20enum LegacySaveFlags {
21    kHasAlphaLayer_LegacySaveFlags    = 0x04,
22    kClipToLayer_LegacySaveFlags      = 0x10,
23};
24
25SkCanvas::SaveLayerFlags SkCanvas::LegacySaveFlagsToSaveLayerFlags(uint32_t flags) {
26    uint32_t layerFlags = 0;
27
28    if (0 == (flags & kClipToLayer_LegacySaveFlags)) {
29        layerFlags |= SkCanvas::kDontClipToLayer_PrivateSaveLayerFlag;
30    }
31    if (0 == (flags & kHasAlphaLayer_LegacySaveFlags)) {
32        layerFlags |= kIsOpaque_SaveLayerFlag;
33    }
34    return layerFlags;
35}
36
37/*
38 * Read the next op code and chunk size from 'reader'. The returned size
39 * is the entire size of the chunk (including the opcode). Thus, the
40 * offset just prior to calling ReadOpAndSize + 'size' is the offset
41 * to the next chunk's op code. This also means that the size of a chunk
42 * with no arguments (just an opcode) will be 4.
43 */
44DrawType SkPicturePlayback::ReadOpAndSize(SkReadBuffer* reader, uint32_t* size) {
45    uint32_t temp = reader->readInt();
46    uint32_t op;
47    if (((uint8_t)temp) == temp) {
48        // old skp file - no size information
49        op = temp;
50        *size = 0;
51    } else {
52        UNPACK_8_24(temp, op, *size);
53        if (MASK_24 == *size) {
54            *size = reader->readInt();
55        }
56    }
57    return (DrawType)op;
58}
59
60
61static const SkRect* get_rect_ptr(SkReadBuffer* reader, SkRect* storage) {
62    if (reader->readBool()) {
63        reader->readRect(storage);
64        return storage;
65    } else {
66        return nullptr;
67    }
68}
69
70class TextContainer {
71public:
72    size_t length() { return fByteLength; }
73    const void* text() { return (const void*)fText; }
74    size_t fByteLength;
75    const char* fText;
76};
77
78void get_text(SkReadBuffer* reader, TextContainer* text) {
79    size_t length = text->fByteLength = reader->readInt();
80    text->fText = (const char*)reader->skip(length);
81}
82
83void SkPicturePlayback::draw(SkCanvas* canvas,
84                             SkPicture::AbortCallback* callback,
85                             SkReadBuffer* buffer) {
86    AutoResetOpID aroi(this);
87    SkASSERT(0 == fCurOffset);
88
89    std::unique_ptr<SkReadBuffer> reader;
90    if (buffer) {
91        reader.reset(buffer->clone(fPictureData->opData()->bytes(),
92                                   fPictureData->opData()->size()));
93    } else {
94        reader.reset(new SkReadBuffer(fPictureData->opData()->bytes(),
95                                      fPictureData->opData()->size()));
96    }
97
98    // Record this, so we can concat w/ it if we encounter a setMatrix()
99    SkMatrix initialMatrix = canvas->getTotalMatrix();
100
101    SkAutoCanvasRestore acr(canvas, false);
102
103    while (!reader->eof()) {
104        if (callback && callback->abort()) {
105            return;
106        }
107
108        fCurOffset = reader->offset();
109        uint32_t size;
110        DrawType op = ReadOpAndSize(reader.get(), &size);
111        if (!reader->validate(op > UNUSED && op <= LAST_DRAWTYPE_ENUM)) {
112            return;
113        }
114
115        this->handleOp(reader.get(), op, size, canvas, initialMatrix);
116    }
117
118    // need to propagate invalid state to the parent reader
119    if (buffer) {
120        buffer->validate(reader->isValid());
121    }
122}
123
124void SkPicturePlayback::handleOp(SkReadBuffer* reader,
125                                 DrawType op,
126                                 uint32_t size,
127                                 SkCanvas* canvas,
128                                 const SkMatrix& initialMatrix) {
129#define BREAK_ON_READ_ERROR(r) if (!r->isValid()) { break; }
130
131    switch (op) {
132        case NOOP: {
133            SkASSERT(size >= 4);
134            reader->skip(size - 4);
135        } break;
136        case CLIP_PATH: {
137            const SkPath& path = fPictureData->getPath(reader);
138            uint32_t packed = reader->readInt();
139            SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed);
140            bool doAA = ClipParams_unpackDoAA(packed);
141            size_t offsetToRestore = reader->readInt();
142            BREAK_ON_READ_ERROR(reader);
143
144            SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
145            canvas->clipPath(path, clipOp, doAA);
146            if (canvas->isClipEmpty() && offsetToRestore) {
147                reader->skip(offsetToRestore - reader->offset());
148            }
149        } break;
150        case CLIP_REGION: {
151            SkRegion region;
152            reader->readRegion(&region);
153            uint32_t packed = reader->readInt();
154            SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed);
155            size_t offsetToRestore = reader->readInt();
156            BREAK_ON_READ_ERROR(reader);
157
158            SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
159            canvas->clipRegion(region, clipOp);
160            if (canvas->isClipEmpty() && offsetToRestore) {
161                reader->skip(offsetToRestore - reader->offset());
162            }
163        } break;
164        case CLIP_RECT: {
165            SkRect rect;
166            reader->readRect(&rect);
167            uint32_t packed = reader->readInt();
168            SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed);
169            bool doAA = ClipParams_unpackDoAA(packed);
170            size_t offsetToRestore = reader->readInt();
171            BREAK_ON_READ_ERROR(reader);
172
173            SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
174            canvas->clipRect(rect, clipOp, doAA);
175            if (canvas->isClipEmpty() && offsetToRestore) {
176                reader->skip(offsetToRestore - reader->offset());
177            }
178        } break;
179        case CLIP_RRECT: {
180            SkRRect rrect;
181            reader->readRRect(&rrect);
182            uint32_t packed = reader->readInt();
183            SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed);
184            bool doAA = ClipParams_unpackDoAA(packed);
185            size_t offsetToRestore = reader->readInt();
186            BREAK_ON_READ_ERROR(reader);
187
188            SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
189            canvas->clipRRect(rrect, clipOp, doAA);
190            if (canvas->isClipEmpty() && offsetToRestore) {
191                reader->skip(offsetToRestore - reader->offset());
192            }
193        } break;
194        case PUSH_CULL: break;  // Deprecated, safe to ignore both push and pop.
195        case POP_CULL:  break;
196        case CONCAT: {
197            SkMatrix matrix;
198            reader->readMatrix(&matrix);
199            BREAK_ON_READ_ERROR(reader);
200
201            canvas->concat(matrix);
202            break;
203        }
204        case DRAW_ANNOTATION: {
205            SkRect rect;
206            reader->readRect(&rect);
207            SkString key;
208            reader->readString(&key);
209            sk_sp<SkData> data = reader->readByteArrayAsData();
210            BREAK_ON_READ_ERROR(reader);
211
212            canvas->drawAnnotation(rect, key.c_str(), data.get());
213        } break;
214        case DRAW_ARC: {
215            const SkPaint* paint = fPictureData->getPaint(reader);
216            SkRect rect;
217            reader->readRect(&rect);
218            SkScalar startAngle = reader->readScalar();
219            SkScalar sweepAngle = reader->readScalar();
220            int useCenter = reader->readInt();
221            BREAK_ON_READ_ERROR(reader);
222
223            if (paint) {
224                canvas->drawArc(rect, startAngle, sweepAngle, SkToBool(useCenter), *paint);
225            }
226        } break;
227        case DRAW_ATLAS: {
228            const SkPaint* paint = fPictureData->getPaint(reader);
229            const SkImage* atlas = fPictureData->getImage(reader);
230            const uint32_t flags = reader->readUInt();
231            const int count = reader->readUInt();
232            const SkRSXform* xform = (const SkRSXform*)reader->skip(count * sizeof(SkRSXform));
233            const SkRect* tex = (const SkRect*)reader->skip(count * sizeof(SkRect));
234            const SkColor* colors = nullptr;
235            SkBlendMode mode = SkBlendMode::kDst;
236            if (flags & DRAW_ATLAS_HAS_COLORS) {
237                colors = (const SkColor*)reader->skip(count * sizeof(SkColor));
238                mode = (SkBlendMode)reader->readUInt();
239            }
240            const SkRect* cull = nullptr;
241            if (flags & DRAW_ATLAS_HAS_CULL) {
242                cull = (const SkRect*)reader->skip(sizeof(SkRect));
243            }
244            BREAK_ON_READ_ERROR(reader);
245
246            canvas->drawAtlas(atlas, xform, tex, colors, count, mode, cull, paint);
247        } break;
248        case DRAW_BITMAP: {
249            const SkPaint* paint = fPictureData->getPaint(reader);
250            const SkImage* image = fPictureData->getBitmapAsImage(reader);
251            SkPoint loc;
252            reader->readPoint(&loc);
253            BREAK_ON_READ_ERROR(reader);
254
255            canvas->drawImage(image, loc.fX, loc.fY, paint);
256        } break;
257        case DRAW_BITMAP_RECT: {
258            const SkPaint* paint = fPictureData->getPaint(reader);
259            const SkImage* image = fPictureData->getBitmapAsImage(reader);
260            SkRect storage;
261            const SkRect* src = get_rect_ptr(reader, &storage);   // may be null
262            SkRect dst;
263            reader->readRect(&dst);     // required
264            SkCanvas::SrcRectConstraint constraint = (SkCanvas::SrcRectConstraint)reader->readInt();
265            BREAK_ON_READ_ERROR(reader);
266
267            if (src) {
268                canvas->drawImageRect(image, *src, dst, paint, constraint);
269            } else {
270                canvas->drawImageRect(image, dst, paint, constraint);
271            }
272        } break;
273        case DRAW_BITMAP_MATRIX: {
274            const SkPaint* paint = fPictureData->getPaint(reader);
275            const SkImage* image = fPictureData->getBitmapAsImage(reader);
276            SkMatrix matrix;
277            reader->readMatrix(&matrix);
278            BREAK_ON_READ_ERROR(reader);
279
280            SkAutoCanvasRestore acr(canvas, true);
281            canvas->concat(matrix);
282            canvas->drawImage(image, 0, 0, paint);
283        } break;
284        case DRAW_BITMAP_NINE: {
285            const SkPaint* paint = fPictureData->getPaint(reader);
286            const SkImage* image = fPictureData->getBitmapAsImage(reader);
287            SkIRect src;
288            reader->readIRect(&src);
289            SkRect dst;
290            reader->readRect(&dst);
291            BREAK_ON_READ_ERROR(reader);
292
293            canvas->drawImageNine(image, src, dst, paint);
294        } break;
295        case DRAW_CLEAR: {
296            auto c = reader->readInt();
297            BREAK_ON_READ_ERROR(reader);
298
299            canvas->clear(c);
300        } break;
301        case DRAW_DATA: {
302            // This opcode is now dead, just need to skip it for backwards compatibility
303            size_t length = reader->readInt();
304            (void)reader->skip(length);
305            // skip handles padding the read out to a multiple of 4
306        } break;
307        case DRAW_DRAWABLE: {
308            auto* d = fPictureData->getDrawable(reader);
309            BREAK_ON_READ_ERROR(reader);
310
311            canvas->drawDrawable(d);
312        } break;
313        case DRAW_DRAWABLE_MATRIX: {
314            SkMatrix matrix;
315            reader->readMatrix(&matrix);
316            SkDrawable* drawable = fPictureData->getDrawable(reader);
317            BREAK_ON_READ_ERROR(reader);
318
319            canvas->drawDrawable(drawable, &matrix);
320        } break;
321        case DRAW_DRRECT: {
322            const SkPaint* paint = fPictureData->getPaint(reader);
323            SkRRect outer, inner;
324            reader->readRRect(&outer);
325            reader->readRRect(&inner);
326            BREAK_ON_READ_ERROR(reader);
327
328            if (paint) {
329                canvas->drawDRRect(outer, inner, *paint);
330            }
331        } break;
332        case BEGIN_COMMENT_GROUP: {
333            SkString tmp;
334            reader->readString(&tmp);
335            // deprecated (M44)
336            break;
337        }
338        case COMMENT: {
339            SkString tmp;
340            reader->readString(&tmp);
341            reader->readString(&tmp);
342            // deprecated (M44)
343            break;
344        }
345        case END_COMMENT_GROUP:
346            // deprecated (M44)
347            break;
348        case DRAW_IMAGE: {
349            const SkPaint* paint = fPictureData->getPaint(reader);
350            const SkImage* image = fPictureData->getImage(reader);
351            SkPoint loc;
352            reader->readPoint(&loc);
353            BREAK_ON_READ_ERROR(reader);
354
355            canvas->drawImage(image, loc.fX, loc.fY, paint);
356        } break;
357        case DRAW_IMAGE_LATTICE: {
358            const SkPaint* paint = fPictureData->getPaint(reader);
359            const SkImage* image = fPictureData->getImage(reader);
360            SkCanvas::Lattice lattice;
361            lattice.fXCount = reader->readInt();
362            lattice.fXDivs = (const int*) reader->skip(lattice.fXCount * sizeof(int32_t));
363            lattice.fYCount = reader->readInt();
364            lattice.fYDivs = (const int*) reader->skip(lattice.fYCount * sizeof(int32_t));
365            int flagCount = reader->readInt();
366            lattice.fFlags = (0 == flagCount) ? nullptr : (const SkCanvas::Lattice::Flags*)
367                    reader->skip(SkAlign4(flagCount * sizeof(SkCanvas::Lattice::Flags)));
368            SkIRect src;
369            reader->readIRect(&src);
370            lattice.fBounds = &src;
371            SkRect dst;
372            reader->readRect(&dst);
373            BREAK_ON_READ_ERROR(reader);
374
375            canvas->drawImageLattice(image, lattice, dst, paint);
376        } break;
377        case DRAW_IMAGE_NINE: {
378            const SkPaint* paint = fPictureData->getPaint(reader);
379            const SkImage* image = fPictureData->getImage(reader);
380            SkIRect center;
381            reader->readIRect(&center);
382            SkRect dst;
383            reader->readRect(&dst);
384            BREAK_ON_READ_ERROR(reader);
385
386            canvas->drawImageNine(image, center, dst, paint);
387        } break;
388        case DRAW_IMAGE_RECT_STRICT:
389        case DRAW_IMAGE_RECT: {
390            const SkPaint* paint = fPictureData->getPaint(reader);
391            const SkImage* image = fPictureData->getImage(reader);
392            SkRect storage;
393            const SkRect* src = get_rect_ptr(reader, &storage);   // may be null
394            SkRect dst;
395            reader->readRect(&dst);     // required
396            // DRAW_IMAGE_RECT_STRICT assumes this constraint, and doesn't store it
397            SkCanvas::SrcRectConstraint constraint = SkCanvas::kStrict_SrcRectConstraint;
398            if (DRAW_IMAGE_RECT == op) {
399                // newer op-code stores the constraint explicitly
400                constraint = (SkCanvas::SrcRectConstraint)reader->readInt();
401            }
402            BREAK_ON_READ_ERROR(reader);
403
404            canvas->legacy_drawImageRect(image, src, dst, paint, constraint);
405        } break;
406        case DRAW_OVAL: {
407            const SkPaint* paint = fPictureData->getPaint(reader);
408            SkRect rect;
409            reader->readRect(&rect);
410            BREAK_ON_READ_ERROR(reader);
411
412            if (paint) {
413                canvas->drawOval(rect, *paint);
414            }
415        } break;
416        case DRAW_PAINT: {
417            const SkPaint* paint = fPictureData->getPaint(reader);
418            BREAK_ON_READ_ERROR(reader);
419
420            if (paint) {
421                canvas->drawPaint(*paint);
422            }
423        } break;
424        case DRAW_PATCH: {
425            const SkPaint* paint = fPictureData->getPaint(reader);
426
427            const SkPoint* cubics = (const SkPoint*)reader->skip(SkPatchUtils::kNumCtrlPts *
428                                                                 sizeof(SkPoint));
429            uint32_t flag = reader->readInt();
430            const SkColor* colors = nullptr;
431            if (flag & DRAW_VERTICES_HAS_COLORS) {
432                colors = (const SkColor*)reader->skip(SkPatchUtils::kNumCorners * sizeof(SkColor));
433            }
434            const SkPoint* texCoords = nullptr;
435            if (flag & DRAW_VERTICES_HAS_TEXS) {
436                texCoords = (const SkPoint*)reader->skip(SkPatchUtils::kNumCorners *
437                                                         sizeof(SkPoint));
438            }
439            SkBlendMode bmode = SkBlendMode::kModulate;
440            if (flag & DRAW_VERTICES_HAS_XFER) {
441                unsigned mode = reader->readInt();
442                if (mode <= (unsigned)SkBlendMode::kLastMode) {
443                    bmode = (SkBlendMode)mode;
444                }
445            }
446            BREAK_ON_READ_ERROR(reader);
447
448            if (paint) {
449                canvas->drawPatch(cubics, colors, texCoords, bmode, *paint);
450            }
451        } break;
452        case DRAW_PATH: {
453            const SkPaint* paint = fPictureData->getPaint(reader);
454            const auto& path = fPictureData->getPath(reader);
455            BREAK_ON_READ_ERROR(reader);
456
457            if (paint) {
458                canvas->drawPath(path, *paint);
459            }
460        } break;
461        case DRAW_PICTURE: {
462            const auto* pic = fPictureData->getPicture(reader);
463            BREAK_ON_READ_ERROR(reader);
464
465            canvas->drawPicture(pic);
466        } break;
467        case DRAW_PICTURE_MATRIX_PAINT: {
468            const SkPaint* paint = fPictureData->getPaint(reader);
469            SkMatrix matrix;
470            reader->readMatrix(&matrix);
471            const SkPicture* pic = fPictureData->getPicture(reader);
472            BREAK_ON_READ_ERROR(reader);
473
474            canvas->drawPicture(pic, &matrix, paint);
475        } break;
476        case DRAW_POINTS: {
477            const SkPaint* paint = fPictureData->getPaint(reader);
478            SkCanvas::PointMode mode = (SkCanvas::PointMode)reader->readInt();
479            size_t count = reader->readInt();
480            const SkPoint* pts = (const SkPoint*)reader->skip(sizeof(SkPoint)* count);
481            BREAK_ON_READ_ERROR(reader);
482
483            if (paint) {
484                canvas->drawPoints(mode, count, pts, *paint);
485            }
486        } break;
487        case DRAW_POS_TEXT: {
488            const SkPaint* paint = fPictureData->getPaint(reader);
489            TextContainer text;
490            get_text(reader, &text);
491            size_t points = reader->readInt();
492            const SkPoint* pos = (const SkPoint*)reader->skip(points * sizeof(SkPoint));
493            BREAK_ON_READ_ERROR(reader);
494
495            if (paint && text.text()) {
496                canvas->drawPosText(text.text(), text.length(), pos, *paint);
497            }
498        } break;
499        case DRAW_POS_TEXT_TOP_BOTTOM: {
500            const SkPaint* paint = fPictureData->getPaint(reader);
501            TextContainer text;
502            get_text(reader, &text);
503            size_t points = reader->readInt();
504            const SkPoint* pos = (const SkPoint*)reader->skip(points * sizeof(SkPoint));
505            const SkScalar top = reader->readScalar();
506            const SkScalar bottom = reader->readScalar();
507            BREAK_ON_READ_ERROR(reader);
508
509            SkRect clip = canvas->getLocalClipBounds();
510            if (top < clip.fBottom && bottom > clip.fTop && paint && text.text()) {
511                canvas->drawPosText(text.text(), text.length(), pos, *paint);
512            }
513        } break;
514        case DRAW_POS_TEXT_H: {
515            const SkPaint* paint = fPictureData->getPaint(reader);
516            TextContainer text;
517            get_text(reader, &text);
518            size_t xCount = reader->readInt();
519            const SkScalar constY = reader->readScalar();
520            const SkScalar* xpos = (const SkScalar*)reader->skip(xCount * sizeof(SkScalar));
521            BREAK_ON_READ_ERROR(reader);
522
523            if (paint && text.text()) {
524                canvas->drawPosTextH(text.text(), text.length(), xpos, constY, *paint);
525            }
526        } break;
527        case DRAW_POS_TEXT_H_TOP_BOTTOM: {
528            const SkPaint* paint = fPictureData->getPaint(reader);
529            TextContainer text;
530            get_text(reader, &text);
531            size_t xCount = reader->readInt();
532            const SkScalar* xpos = (const SkScalar*)reader->skip((3 + xCount) * sizeof(SkScalar));
533            BREAK_ON_READ_ERROR(reader);
534
535            const SkScalar top = *xpos++;
536            const SkScalar bottom = *xpos++;
537            const SkScalar constY = *xpos++;
538            SkRect clip = canvas->getLocalClipBounds();
539            if (top < clip.fBottom && bottom > clip.fTop && paint && text.text()) {
540                canvas->drawPosTextH(text.text(), text.length(), xpos, constY, *paint);
541            }
542        } break;
543        case DRAW_RECT: {
544            const SkPaint* paint = fPictureData->getPaint(reader);
545            SkRect rect;
546            reader->readRect(&rect);
547            BREAK_ON_READ_ERROR(reader);
548
549            if (paint) {
550                canvas->drawRect(rect, *paint);
551            }
552        } break;
553        case DRAW_REGION: {
554            const SkPaint* paint = fPictureData->getPaint(reader);
555            SkRegion region;
556            reader->readRegion(&region);
557            BREAK_ON_READ_ERROR(reader);
558
559            if (paint) {
560                canvas->drawRegion(region, *paint);
561            }
562        } break;
563        case DRAW_RRECT: {
564            const SkPaint* paint = fPictureData->getPaint(reader);
565            SkRRect rrect;
566            reader->readRRect(&rrect);
567            BREAK_ON_READ_ERROR(reader);
568
569            if (paint) {
570                canvas->drawRRect(rrect, *paint);
571            }
572        } break;
573        case DRAW_SPRITE: {
574            /* const SkPaint* paint = */ fPictureData->getPaint(reader);
575            /* const SkImage* image = */ fPictureData->getBitmapAsImage(reader);
576            /* int left = */ reader->readInt();
577            /* int top = */ reader->readInt();
578            // drawSprite removed dec-2015
579        } break;
580        case DRAW_TEXT: {
581            const SkPaint* paint = fPictureData->getPaint(reader);
582            TextContainer text;
583            get_text(reader, &text);
584            SkScalar x = reader->readScalar();
585            SkScalar y = reader->readScalar();
586            BREAK_ON_READ_ERROR(reader);
587
588            if (paint && text.text()) {
589                canvas->drawText(text.text(), text.length(), x, y, *paint);
590            }
591        } break;
592        case DRAW_TEXT_BLOB: {
593            const SkPaint* paint = fPictureData->getPaint(reader);
594            const SkTextBlob* blob = fPictureData->getTextBlob(reader);
595            SkScalar x = reader->readScalar();
596            SkScalar y = reader->readScalar();
597            BREAK_ON_READ_ERROR(reader);
598
599            if (paint) {
600                canvas->drawTextBlob(blob, x, y, *paint);
601            }
602        } break;
603        case DRAW_TEXT_TOP_BOTTOM: {
604            const SkPaint* paint = fPictureData->getPaint(reader);
605            TextContainer text;
606            get_text(reader, &text);
607            const SkScalar* ptr = (const SkScalar*)reader->skip(4 * sizeof(SkScalar));
608            BREAK_ON_READ_ERROR(reader);
609
610            // ptr[0] == x
611            // ptr[1] == y
612            // ptr[2] == top
613            // ptr[3] == bottom
614            SkRect clip = canvas->getLocalClipBounds();
615            float top = ptr[2];
616            float bottom = ptr[3];
617            if (top < clip.fBottom && bottom > clip.fTop && paint && text.text()) {
618                canvas->drawText(text.text(), text.length(), ptr[0], ptr[1], *paint);
619            }
620        } break;
621        case DRAW_TEXT_ON_PATH: {
622            const SkPaint* paint = fPictureData->getPaint(reader);
623            TextContainer text;
624            get_text(reader, &text);
625            const SkPath& path = fPictureData->getPath(reader);
626            SkMatrix matrix;
627            reader->readMatrix(&matrix);
628            BREAK_ON_READ_ERROR(reader);
629
630            if (paint && text.text()) {
631                canvas->drawTextOnPath(text.text(), text.length(), path, &matrix, *paint);
632            }
633        } break;
634        case DRAW_TEXT_RSXFORM: {
635            const SkPaint* paint = fPictureData->getPaint(reader);
636            int count = reader->readInt();
637            uint32_t flags = reader->read32();
638            TextContainer text;
639            get_text(reader, &text);
640            const SkRSXform* xform = (const SkRSXform*)reader->skip(count * sizeof(SkRSXform));
641            const SkRect* cull = nullptr;
642            if (flags & DRAW_TEXT_RSXFORM_HAS_CULL) {
643                cull = (const SkRect*)reader->skip(sizeof(SkRect));
644            }
645            BREAK_ON_READ_ERROR(reader);
646
647            if (text.text()) {
648                canvas->drawTextRSXform(text.text(), text.length(), xform, cull, *paint);
649            }
650        } break;
651        case DRAW_VERTICES_RETIRED_03_2017: {
652            const SkPaint* paint = fPictureData->getPaint(reader);
653            DrawVertexFlags flags = (DrawVertexFlags)reader->readInt();
654            SkCanvas::VertexMode vmode = (SkCanvas::VertexMode)reader->readInt();
655            int vCount = reader->readInt();
656            const SkPoint* verts = (const SkPoint*)reader->skip(vCount * sizeof(SkPoint));
657            const SkPoint* texs = nullptr;
658            const SkColor* colors = nullptr;
659            const uint16_t* indices = nullptr;
660            int iCount = 0;
661            if (flags & DRAW_VERTICES_HAS_TEXS) {
662                texs = (const SkPoint*)reader->skip(vCount * sizeof(SkPoint));
663            }
664            if (flags & DRAW_VERTICES_HAS_COLORS) {
665                colors = (const SkColor*)reader->skip(vCount * sizeof(SkColor));
666            }
667            if (flags & DRAW_VERTICES_HAS_INDICES) {
668                iCount = reader->readInt();
669                indices = (const uint16_t*)reader->skip(iCount * sizeof(uint16_t));
670            }
671            SkBlendMode bmode = SkBlendMode::kModulate;
672            if (flags & DRAW_VERTICES_HAS_XFER) {
673                unsigned mode = reader->readInt();
674                if (mode <= (unsigned)SkBlendMode::kLastMode) {
675                    bmode = (SkBlendMode)mode;
676                }
677            }
678            BREAK_ON_READ_ERROR(reader);
679
680            if (paint) {
681                canvas->drawVertices(SkVertices::MakeCopy(vmode, vCount, verts, texs, colors,
682                                                          iCount, indices), bmode, *paint);
683            }
684        } break;
685        case DRAW_VERTICES_OBJECT: {
686            const SkPaint* paint = fPictureData->getPaint(reader);
687            const SkVertices* vertices = fPictureData->getVertices(reader);
688            SkBlendMode bmode = static_cast<SkBlendMode>(reader->readInt());
689
690            BREAK_ON_READ_ERROR(reader);
691
692            if (paint && vertices) {
693                canvas->drawVertices(vertices, bmode, *paint);
694            }
695        } break;
696        case RESTORE:
697            canvas->restore();
698            break;
699        case ROTATE: {
700            auto deg = reader->readScalar();
701            BREAK_ON_READ_ERROR(reader);
702
703            canvas->rotate(deg);
704        } break;
705        case SAVE:
706            canvas->save();
707            break;
708        case SAVE_LAYER_SAVEFLAGS_DEPRECATED: {
709            SkRect storage;
710            const SkRect* boundsPtr = get_rect_ptr(reader, &storage);
711            const SkPaint* paint = fPictureData->getPaint(reader);
712            auto flags = SkCanvas::LegacySaveFlagsToSaveLayerFlags(reader->readInt());
713            BREAK_ON_READ_ERROR(reader);
714
715            canvas->saveLayer(SkCanvas::SaveLayerRec(boundsPtr, paint, flags));
716        } break;
717        case SAVE_LAYER_SAVELAYERFLAGS_DEPRECATED_JAN_2016: {
718            SkRect storage;
719            const SkRect* boundsPtr = get_rect_ptr(reader, &storage);
720            const SkPaint* paint = fPictureData->getPaint(reader);
721            auto flags = reader->readInt();
722            BREAK_ON_READ_ERROR(reader);
723
724            canvas->saveLayer(SkCanvas::SaveLayerRec(boundsPtr, paint, flags));
725        } break;
726        case SAVE_LAYER_SAVELAYERREC: {
727            SkCanvas::SaveLayerRec rec(nullptr, nullptr, nullptr, 0);
728            const uint32_t flatFlags = reader->readInt();
729            SkRect bounds;
730            if (flatFlags & SAVELAYERREC_HAS_BOUNDS) {
731                reader->readRect(&bounds);
732                rec.fBounds = &bounds;
733            }
734            if (flatFlags & SAVELAYERREC_HAS_PAINT) {
735                rec.fPaint = fPictureData->getPaint(reader);
736            }
737            if (flatFlags & SAVELAYERREC_HAS_BACKDROP) {
738                if (const auto* paint = fPictureData->getPaint(reader)) {
739                    rec.fBackdrop = paint->getImageFilter();
740                }
741            }
742            if (flatFlags & SAVELAYERREC_HAS_FLAGS) {
743                rec.fSaveLayerFlags = reader->readInt();
744            }
745            BREAK_ON_READ_ERROR(reader);
746
747            canvas->saveLayer(rec);
748        } break;
749        case SCALE: {
750            SkScalar sx = reader->readScalar();
751            SkScalar sy = reader->readScalar();
752            BREAK_ON_READ_ERROR(reader);
753
754            canvas->scale(sx, sy);
755        } break;
756        case SET_MATRIX: {
757            SkMatrix matrix;
758            reader->readMatrix(&matrix);
759            BREAK_ON_READ_ERROR(reader);
760
761            matrix.postConcat(initialMatrix);
762            canvas->setMatrix(matrix);
763        } break;
764        case SKEW: {
765            SkScalar sx = reader->readScalar();
766            SkScalar sy = reader->readScalar();
767            BREAK_ON_READ_ERROR(reader);
768
769            canvas->skew(sx, sy);
770        } break;
771        case TRANSLATE: {
772            SkScalar dx = reader->readScalar();
773            SkScalar dy = reader->readScalar();
774            BREAK_ON_READ_ERROR(reader);
775
776            canvas->translate(dx, dy);
777        } break;
778        case TRANSLATE_Z: {
779#ifdef SK_EXPERIMENTAL_SHADOWING
780            SkScalar dz = reader->readScalar();
781            BREAK_ON_READ_ERROR(reader);
782
783            canvas->translateZ(dz);
784#endif
785        } break;
786        default:
787            SkASSERTF(false, "Unknown draw type: %d", op);
788    }
789
790#undef BREAK_ON_READ_ERROR
791}
792