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 "include/core/SkCanvas.h"
9#include "include/core/SkRSXform.h"
10#include "include/core/SkTextBlob.h"
11#include "include/core/SkTypes.h"
12#include "include/private/SkTDArray.h"
13#include "src/core/SkCanvasPriv.h"
14#include "src/core/SkDrawShadowInfo.h"
15#include "src/core/SkFontPriv.h"
16#include "src/core/SkPaintPriv.h"
17#include "src/core/SkPictureData.h"
18#include "src/core/SkPicturePlayback.h"
19#include "src/core/SkPictureRecord.h"
20#include "src/core/SkReadBuffer.h"
21#include "src/core/SkSafeMath.h"
22#include "src/core/SkSamplingPriv.h"
23#include "src/core/SkVerticesPriv.h"
24#include "src/utils/SkPatchUtils.h"
25
26static const SkRect* get_rect_ptr(SkReadBuffer* reader, SkRect* storage) {
27    if (reader->readBool()) {
28        reader->readRect(storage);
29        return storage;
30    } else {
31        return nullptr;
32    }
33}
34
35void SkPicturePlayback::draw(SkCanvas* canvas,
36                             SkPicture::AbortCallback* callback,
37                             SkReadBuffer* buffer) {
38    AutoResetOpID aroi(this);
39    SkASSERT(0 == fCurOffset);
40
41    SkReadBuffer reader(fPictureData->opData()->bytes(),
42                        fPictureData->opData()->size());
43
44    // Record this, so we can concat w/ it if we encounter a setMatrix()
45    SkM44 initialMatrix = canvas->getLocalToDevice();
46
47    SkAutoCanvasRestore acr(canvas, false);
48
49    while (!reader.eof() && reader.isValid()) {
50        if (callback && callback->abort()) {
51            return;
52        }
53
54        fCurOffset = reader.offset();
55
56        uint32_t bits = reader.readInt();
57        uint32_t op   = bits >> 24,
58                 size = bits & 0xffffff;
59        if (size == 0xffffff) {
60            size = reader.readInt();
61        }
62
63        if (!reader.validate(size > 0 && op > UNUSED && op <= LAST_DRAWTYPE_ENUM)) {
64            return;
65        }
66
67        this->handleOp(&reader, (DrawType)op, size, canvas, initialMatrix);
68    }
69
70    // need to propagate invalid state to the parent reader
71    if (buffer) {
72        buffer->validate(reader.isValid());
73    }
74}
75
76static void validate_offsetToRestore(SkReadBuffer* reader, size_t offsetToRestore) {
77    if (offsetToRestore) {
78        reader->validate(SkIsAlign4(offsetToRestore) && offsetToRestore >= reader->offset());
79    }
80}
81
82static bool do_clip_op(SkReadBuffer* reader, SkCanvas* canvas, SkRegion::Op op,
83                       SkClipOp* clipOpToUse) {
84    switch(op) {
85        case SkRegion::kDifference_Op:
86        case SkRegion::kIntersect_Op:
87            // Fully supported, identity mapping between SkClipOp and Region::Op
88            *clipOpToUse = static_cast<SkClipOp>(op);
89            return true;
90        case SkRegion::kReplace_Op:
91            // Emulate the replace by resetting first and following it up with an intersect
92            SkASSERT(reader->isVersionLT(SkPicturePriv::kNoExpandingClipOps));
93            SkCanvasPriv::ResetClip(canvas);
94            *clipOpToUse = SkClipOp::kIntersect;
95            return true;
96        default:
97            // An expanding clip op, which if encountered on an old SKP, we just silently ignore
98            SkASSERT(reader->isVersionLT(SkPicturePriv::kNoExpandingClipOps));
99            return false;
100    }
101}
102
103void SkPicturePlayback::handleOp(SkReadBuffer* reader,
104                                 DrawType op,
105                                 uint32_t size,
106                                 SkCanvas* canvas,
107                                 const SkM44& initialMatrix) {
108#define BREAK_ON_READ_ERROR(r)  if (!r->isValid()) break
109
110    switch (op) {
111        case NOOP: {
112            SkASSERT(size >= 4);
113            reader->skip(size - 4);
114        } break;
115        case FLUSH:
116            canvas->flush();
117            break;
118        case CLIP_PATH: {
119            const SkPath& path = fPictureData->getPath(reader);
120            uint32_t packed = reader->readInt();
121            SkRegion::Op rgnOp = ClipParams_unpackRegionOp(reader, packed);
122            bool doAA = ClipParams_unpackDoAA(packed);
123            size_t offsetToRestore = reader->readInt();
124            validate_offsetToRestore(reader, offsetToRestore);
125            BREAK_ON_READ_ERROR(reader);
126
127            SkClipOp clipOp;
128            if (do_clip_op(reader, canvas, rgnOp, &clipOp)) {
129                canvas->clipPath(path, clipOp, doAA);
130            }
131            if (canvas->isClipEmpty() && offsetToRestore) {
132                reader->skip(offsetToRestore - reader->offset());
133            }
134        } break;
135        case CLIP_REGION: {
136            SkRegion region;
137            reader->readRegion(&region);
138            uint32_t packed = reader->readInt();
139            SkRegion::Op rgnOp = ClipParams_unpackRegionOp(reader, packed);
140            size_t offsetToRestore = reader->readInt();
141            validate_offsetToRestore(reader, offsetToRestore);
142            BREAK_ON_READ_ERROR(reader);
143
144            SkClipOp clipOp;
145            if (do_clip_op(reader, canvas, rgnOp, &clipOp)) {
146                canvas->clipRegion(region, clipOp);
147            }
148            if (canvas->isClipEmpty() && offsetToRestore) {
149                reader->skip(offsetToRestore - reader->offset());
150            }
151        } break;
152        case CLIP_RECT: {
153            SkRect rect;
154            reader->readRect(&rect);
155            uint32_t packed = reader->readInt();
156            SkRegion::Op rgnOp = ClipParams_unpackRegionOp(reader, packed);
157            bool doAA = ClipParams_unpackDoAA(packed);
158            size_t offsetToRestore = reader->readInt();
159            validate_offsetToRestore(reader, offsetToRestore);
160            BREAK_ON_READ_ERROR(reader);
161
162            SkClipOp clipOp;
163            if (do_clip_op(reader, canvas, rgnOp, &clipOp)) {
164                canvas->clipRect(rect, clipOp, doAA);
165            }
166            if (canvas->isClipEmpty() && offsetToRestore) {
167                reader->skip(offsetToRestore - reader->offset());
168            }
169        } break;
170        case CLIP_RRECT: {
171            SkRRect rrect;
172            reader->readRRect(&rrect);
173            uint32_t packed = reader->readInt();
174            SkRegion::Op rgnOp = ClipParams_unpackRegionOp(reader, packed);
175            bool doAA = ClipParams_unpackDoAA(packed);
176            size_t offsetToRestore = reader->readInt();
177            validate_offsetToRestore(reader, offsetToRestore);
178            BREAK_ON_READ_ERROR(reader);
179
180            SkClipOp clipOp;
181            if (do_clip_op(reader, canvas, rgnOp, &clipOp)) {
182                canvas->clipRRect(rrect, clipOp, doAA);
183            }
184            if (canvas->isClipEmpty() && offsetToRestore) {
185                reader->skip(offsetToRestore - reader->offset());
186            }
187        } break;
188        case CLIP_SHADER_IN_PAINT: {
189            const SkPaint& paint = fPictureData->requiredPaint(reader);
190            // clipShader() was never used in conjunction with deprecated, expanding clip ops, so
191            // it requires the op to just be intersect or difference.
192            SkClipOp clipOp = reader->checkRange(SkClipOp::kDifference, SkClipOp::kIntersect);
193            BREAK_ON_READ_ERROR(reader);
194
195            canvas->clipShader(paint.refShader(), clipOp);
196        } break;
197        case RESET_CLIP:
198            // For Android, an emulated "replace" clip op appears as a manual reset followed by
199            // an intersect operation (equivalent to the above handling of replace ops encountered
200            // in old serialized pictures).
201            SkCanvasPriv::ResetClip(canvas);
202            break;
203        case PUSH_CULL: break;  // Deprecated, safe to ignore both push and pop.
204        case POP_CULL:  break;
205        case CONCAT: {
206            SkMatrix matrix;
207            reader->readMatrix(&matrix);
208            BREAK_ON_READ_ERROR(reader);
209
210            canvas->concat(matrix);
211            break;
212        }
213        case CONCAT44: {
214            const SkScalar* colMaj = reader->skipT<SkScalar>(16);
215            BREAK_ON_READ_ERROR(reader);
216            canvas->concat(SkM44::ColMajor(colMaj));
217            break;
218        }
219        case DRAW_ANNOTATION: {
220            SkRect rect;
221            reader->readRect(&rect);
222            SkString key;
223            reader->readString(&key);
224            sk_sp<SkData> data = reader->readByteArrayAsData();
225            BREAK_ON_READ_ERROR(reader);
226            SkASSERT(data);
227
228            canvas->drawAnnotation(rect, key.c_str(), data.get());
229        } break;
230        case DRAW_ARC: {
231            const SkPaint& paint = fPictureData->requiredPaint(reader);
232            SkRect rect;
233            reader->readRect(&rect);
234            SkScalar startAngle = reader->readScalar();
235            SkScalar sweepAngle = reader->readScalar();
236            int useCenter = reader->readInt();
237            BREAK_ON_READ_ERROR(reader);
238
239            canvas->drawArc(rect, startAngle, sweepAngle, SkToBool(useCenter), paint);
240        } break;
241        case DRAW_ATLAS: {
242            const SkPaint* paint = fPictureData->optionalPaint(reader);
243            const SkImage* atlas = fPictureData->getImage(reader);
244            const uint32_t flags = reader->readUInt();
245            const int count = reader->readUInt();
246            const SkRSXform* xform = (const SkRSXform*)reader->skip(count, sizeof(SkRSXform));
247            const SkRect* tex = (const SkRect*)reader->skip(count, sizeof(SkRect));
248            const SkColor* colors = nullptr;
249            SkBlendMode mode = SkBlendMode::kDst;
250            if (flags & DRAW_ATLAS_HAS_COLORS) {
251                colors = (const SkColor*)reader->skip(count, sizeof(SkColor));
252                mode = (SkBlendMode)reader->readUInt();
253            }
254            const SkRect* cull = nullptr;
255            if (flags & DRAW_ATLAS_HAS_CULL) {
256                cull = (const SkRect*)reader->skip(sizeof(SkRect));
257            }
258            BREAK_ON_READ_ERROR(reader);
259
260            SkSamplingOptions sampling;
261            if (flags & DRAW_ATLAS_HAS_SAMPLING) {
262                sampling = reader->readSampling();
263                BREAK_ON_READ_ERROR(reader);
264            }
265            canvas->drawAtlas(atlas, xform, tex, colors, count, mode, sampling, cull, paint);
266        } break;
267        case DRAW_CLEAR: {
268            auto c = reader->readInt();
269            BREAK_ON_READ_ERROR(reader);
270
271            canvas->clear(c);
272        } break;
273        case DRAW_DATA: {
274            // This opcode is now dead, just need to skip it for backwards compatibility
275            size_t length = reader->readInt();
276            (void)reader->skip(length);
277            // skip handles padding the read out to a multiple of 4
278        } break;
279        case DRAW_DRAWABLE: {
280            auto* d = fPictureData->getDrawable(reader);
281            BREAK_ON_READ_ERROR(reader);
282
283            canvas->drawDrawable(d);
284        } break;
285        case DRAW_DRAWABLE_MATRIX: {
286            SkMatrix matrix;
287            reader->readMatrix(&matrix);
288            SkDrawable* drawable = fPictureData->getDrawable(reader);
289            BREAK_ON_READ_ERROR(reader);
290
291            canvas->drawDrawable(drawable, &matrix);
292        } break;
293        case DRAW_DRRECT: {
294            const SkPaint& paint = fPictureData->requiredPaint(reader);
295            SkRRect outer, inner;
296            reader->readRRect(&outer);
297            reader->readRRect(&inner);
298            BREAK_ON_READ_ERROR(reader);
299
300            canvas->drawDRRect(outer, inner, paint);
301        } break;
302        case DRAW_EDGEAA_QUAD: {
303            SkRect rect;
304            reader->readRect(&rect);
305            SkCanvas::QuadAAFlags aaFlags = static_cast<SkCanvas::QuadAAFlags>(reader->read32());
306            SkColor4f color;
307            reader->readColor4f(&color);
308            SkBlendMode blend = static_cast<SkBlendMode>(reader->read32());
309            bool hasClip = reader->readInt();
310            SkPoint* clip = nullptr;
311            if (hasClip) {
312                clip = (SkPoint*) reader->skip(4, sizeof(SkPoint));
313            }
314            BREAK_ON_READ_ERROR(reader);
315            canvas->experimental_DrawEdgeAAQuad(rect, clip, aaFlags, color, blend);
316        } break;
317        case DRAW_EDGEAA_IMAGE_SET:
318        case DRAW_EDGEAA_IMAGE_SET2: {
319            static const size_t kEntryReadSize =
320                    4 * sizeof(uint32_t) + 2 * sizeof(SkRect) + sizeof(SkScalar);
321            static const size_t kMatrixSize = 9 * sizeof(SkScalar); // != sizeof(SkMatrix)
322
323            int cnt = reader->readInt();
324            if (!reader->validate(cnt >= 0)) {
325                break;
326            }
327            const SkPaint* paint = fPictureData->optionalPaint(reader);
328
329            SkSamplingOptions sampling;
330            if (op == DRAW_EDGEAA_IMAGE_SET2) {
331                sampling = reader->readSampling();
332            } else {
333                sampling = SkSamplingOptions(SkFilterMode::kNearest);
334            }
335
336            SkCanvas::SrcRectConstraint constraint =
337                    reader->checkRange(SkCanvas::kStrict_SrcRectConstraint,
338                                       SkCanvas::kFast_SrcRectConstraint);
339
340            if (!reader->validate(SkSafeMath::Mul(cnt, kEntryReadSize) <= reader->available())) {
341                break;
342            }
343
344            // Track minimum necessary clip points and matrices that must be provided to satisfy
345            // the entries.
346            int expectedClips = 0;
347            int maxMatrixIndex = -1;
348            SkAutoTArray<SkCanvas::ImageSetEntry> set(cnt);
349            for (int i = 0; i < cnt && reader->isValid(); ++i) {
350                set[i].fImage = sk_ref_sp(fPictureData->getImage(reader));
351                reader->readRect(&set[i].fSrcRect);
352                reader->readRect(&set[i].fDstRect);
353                set[i].fMatrixIndex = reader->readInt();
354                set[i].fAlpha = reader->readScalar();
355                set[i].fAAFlags = reader->readUInt();
356                set[i].fHasClip = reader->readInt();
357
358                expectedClips += set[i].fHasClip ? 1 : 0;
359                if (set[i].fMatrixIndex > maxMatrixIndex) {
360                    maxMatrixIndex = set[i].fMatrixIndex;
361                }
362            }
363
364            int dstClipCount = reader->readInt();
365            SkPoint* dstClips = nullptr;
366            if (!reader->validate(expectedClips <= dstClipCount)) {
367                // Entries request more dstClip points than are provided in the buffer
368                break;
369            } else if (dstClipCount > 0) {
370                dstClips = (SkPoint*) reader->skip(dstClipCount, sizeof(SkPoint));
371                if (dstClips == nullptr) {
372                    // Not enough bytes remaining so the reader has been invalidated
373                    break;
374                }
375            }
376            int matrixCount = reader->readInt();
377            if (!reader->validate((maxMatrixIndex + 1) <= matrixCount) ||
378                !reader->validate(
379                    SkSafeMath::Mul(matrixCount, kMatrixSize) <= reader->available())) {
380                // Entries access out-of-bound matrix indices, given provided matrices or
381                // there aren't enough bytes to provide that many matrices
382                break;
383            }
384            SkTArray<SkMatrix> matrices(matrixCount);
385            for (int i = 0; i < matrixCount && reader->isValid(); ++i) {
386                reader->readMatrix(&matrices.push_back());
387            }
388            BREAK_ON_READ_ERROR(reader);
389
390            canvas->experimental_DrawEdgeAAImageSet(set.get(), cnt, dstClips, matrices.begin(),
391                                                    sampling, paint, constraint);
392        } break;
393        case DRAW_IMAGE: {
394            const SkPaint* paint = fPictureData->optionalPaint(reader);
395            const SkImage* image = fPictureData->getImage(reader);
396            SkPoint loc;
397            reader->readPoint(&loc);
398            BREAK_ON_READ_ERROR(reader);
399
400            canvas->drawImage(image, loc.fX, loc.fY,
401                              SkSamplingOptions(SkFilterMode::kNearest),
402                              paint);
403        } break;
404        case DRAW_IMAGE2: {
405            const SkPaint* paint = fPictureData->optionalPaint(reader);
406            const SkImage* image = fPictureData->getImage(reader);
407            SkPoint loc;
408            reader->readPoint(&loc);
409            SkSamplingOptions sampling = reader->readSampling();
410            BREAK_ON_READ_ERROR(reader);
411
412            canvas->drawImage(image, loc.fX, loc.fY, sampling, paint);
413        } break;
414        case DRAW_IMAGE_LATTICE: {
415            const SkPaint* paint = fPictureData->optionalPaint(reader);
416            const SkImage* image = fPictureData->getImage(reader);
417            SkCanvas::Lattice lattice;
418            (void)SkCanvasPriv::ReadLattice(*reader, &lattice);
419            const SkRect* dst = reader->skipT<SkRect>();
420            BREAK_ON_READ_ERROR(reader);
421
422            canvas->drawImageLattice(image, lattice, *dst, SkFilterMode::kNearest, paint);
423        } break;
424        case DRAW_IMAGE_LATTICE2: {
425            const SkPaint* paint = fPictureData->optionalPaint(reader);
426            const SkImage* image = fPictureData->getImage(reader);
427            SkCanvas::Lattice lattice;
428            (void)SkCanvasPriv::ReadLattice(*reader, &lattice);
429            const SkRect* dst = reader->skipT<SkRect>();
430            SkFilterMode filter = reader->read32LE(SkFilterMode::kLinear);
431            BREAK_ON_READ_ERROR(reader);
432
433            canvas->drawImageLattice(image, lattice, *dst, filter, paint);
434        } break;
435        case DRAW_IMAGE_NINE: {
436            const SkPaint* paint = fPictureData->optionalPaint(reader);
437            const SkImage* image = fPictureData->getImage(reader);
438            SkIRect center;
439            reader->readIRect(&center);
440            SkRect dst;
441            reader->readRect(&dst);
442            BREAK_ON_READ_ERROR(reader);
443
444            canvas->drawImageNine(image, center, dst, SkFilterMode::kNearest, paint);
445        } break;
446        case DRAW_IMAGE_RECT: {
447            const SkPaint* paint = fPictureData->optionalPaint(reader);
448            const SkImage* image = fPictureData->getImage(reader);
449            SkRect storage;
450            const SkRect* src = get_rect_ptr(reader, &storage);   // may be null
451            SkRect dst;
452            reader->readRect(&dst);     // required
453            // DRAW_IMAGE_RECT_STRICT assumes this constraint, and doesn't store it
454            SkCanvas::SrcRectConstraint constraint = SkCanvas::kStrict_SrcRectConstraint;
455            if (DRAW_IMAGE_RECT == op) {
456                // newer op-code stores the constraint explicitly
457                constraint = reader->checkRange(SkCanvas::kStrict_SrcRectConstraint,
458                                                SkCanvas::kFast_SrcRectConstraint);
459            }
460            BREAK_ON_READ_ERROR(reader);
461
462            auto sampling = SkSamplingOptions(SkFilterMode::kNearest);
463            if (src) {
464                canvas->drawImageRect(image, *src, dst, sampling, paint, constraint);
465            } else {
466                canvas->drawImageRect(image, dst, sampling, paint);
467            }
468        } break;
469        case DRAW_IMAGE_RECT2: {
470            const SkPaint* paint = fPictureData->optionalPaint(reader);
471            const SkImage* image = fPictureData->getImage(reader);
472            SkRect src = reader->readRect();
473            SkRect dst = reader->readRect();
474            SkSamplingOptions sampling = reader->readSampling();
475            auto constraint = reader->read32LE(SkCanvas::kFast_SrcRectConstraint);
476            BREAK_ON_READ_ERROR(reader);
477
478            canvas->drawImageRect(image, src, dst, sampling, paint, constraint);
479        } break;
480        case DRAW_OVAL: {
481            const SkPaint& paint = fPictureData->requiredPaint(reader);
482            SkRect rect;
483            reader->readRect(&rect);
484            BREAK_ON_READ_ERROR(reader);
485
486            canvas->drawOval(rect, paint);
487        } break;
488        case DRAW_PAINT: {
489            const SkPaint& paint = fPictureData->requiredPaint(reader);
490            BREAK_ON_READ_ERROR(reader);
491
492            canvas->drawPaint(paint);
493        } break;
494        case DRAW_BEHIND_PAINT: {
495            const SkPaint& paint = fPictureData->requiredPaint(reader);
496            BREAK_ON_READ_ERROR(reader);
497
498            SkCanvasPriv::DrawBehind(canvas, paint);
499        } break;
500        case DRAW_PATCH: {
501            const SkPaint& paint = fPictureData->requiredPaint(reader);
502
503            const SkPoint* cubics = (const SkPoint*)reader->skip(SkPatchUtils::kNumCtrlPts,
504                                                                 sizeof(SkPoint));
505            uint32_t flag = reader->readInt();
506            const SkColor* colors = nullptr;
507            if (flag & DRAW_VERTICES_HAS_COLORS) {
508                colors = (const SkColor*)reader->skip(SkPatchUtils::kNumCorners, sizeof(SkColor));
509            }
510            const SkPoint* texCoords = nullptr;
511            if (flag & DRAW_VERTICES_HAS_TEXS) {
512                texCoords = (const SkPoint*)reader->skip(SkPatchUtils::kNumCorners,
513                                                         sizeof(SkPoint));
514            }
515            SkBlendMode bmode = SkBlendMode::kModulate;
516            if (flag & DRAW_VERTICES_HAS_XFER) {
517                unsigned mode = reader->readInt();
518                if (mode <= (unsigned)SkBlendMode::kLastMode) {
519                    bmode = (SkBlendMode)mode;
520                }
521            }
522            BREAK_ON_READ_ERROR(reader);
523
524            canvas->drawPatch(cubics, colors, texCoords, bmode, paint);
525        } break;
526        case DRAW_PATH: {
527            const SkPaint& paint = fPictureData->requiredPaint(reader);
528            const auto& path = fPictureData->getPath(reader);
529            BREAK_ON_READ_ERROR(reader);
530
531            canvas->drawPath(path, paint);
532        } break;
533        case DRAW_PICTURE: {
534            const auto* pic = fPictureData->getPicture(reader);
535            BREAK_ON_READ_ERROR(reader);
536
537            canvas->drawPicture(pic);
538        } break;
539        case DRAW_PICTURE_MATRIX_PAINT: {
540            const SkPaint* paint = fPictureData->optionalPaint(reader);
541            SkMatrix matrix;
542            reader->readMatrix(&matrix);
543            const SkPicture* pic = fPictureData->getPicture(reader);
544            BREAK_ON_READ_ERROR(reader);
545
546            canvas->drawPicture(pic, &matrix, paint);
547        } break;
548        case DRAW_POINTS: {
549            const SkPaint& paint = fPictureData->requiredPaint(reader);
550            SkCanvas::PointMode mode = reader->checkRange(SkCanvas::kPoints_PointMode,
551                                                          SkCanvas::kPolygon_PointMode);
552            size_t count = reader->readInt();
553            const SkPoint* pts = (const SkPoint*)reader->skip(count, sizeof(SkPoint));
554            BREAK_ON_READ_ERROR(reader);
555
556            canvas->drawPoints(mode, count, pts, paint);
557        } break;
558        case DRAW_RECT: {
559            const SkPaint& paint = fPictureData->requiredPaint(reader);
560            SkRect rect;
561            reader->readRect(&rect);
562            BREAK_ON_READ_ERROR(reader);
563
564            canvas->drawRect(rect, paint);
565        } break;
566        case DRAW_REGION: {
567            const SkPaint& paint = fPictureData->requiredPaint(reader);
568            SkRegion region;
569            reader->readRegion(&region);
570            BREAK_ON_READ_ERROR(reader);
571
572            canvas->drawRegion(region, paint);
573        } break;
574        case DRAW_RRECT: {
575            const SkPaint& paint = fPictureData->requiredPaint(reader);
576            SkRRect rrect;
577            reader->readRRect(&rrect);
578            BREAK_ON_READ_ERROR(reader);
579
580            canvas->drawRRect(rrect, paint);
581        } break;
582        case DRAW_SHADOW_REC: {
583            const auto& path = fPictureData->getPath(reader);
584            SkDrawShadowRec rec;
585            reader->readPoint3(&rec.fZPlaneParams);
586            reader->readPoint3(&rec.fLightPos);
587            rec.fLightRadius = reader->readScalar();
588            rec.fAmbientColor = reader->read32();
589            rec.fSpotColor = reader->read32();
590            rec.fFlags = reader->read32();
591            BREAK_ON_READ_ERROR(reader);
592
593            canvas->private_draw_shadow_rec(path, rec);
594        } break;
595        case DRAW_TEXT_BLOB: {
596            const SkPaint& paint = fPictureData->requiredPaint(reader);
597            const SkTextBlob* blob = fPictureData->getTextBlob(reader);
598            SkScalar x = reader->readScalar();
599            SkScalar y = reader->readScalar();
600            BREAK_ON_READ_ERROR(reader);
601
602            canvas->drawTextBlob(blob, x, y, paint);
603        } break;
604        case DRAW_VERTICES_OBJECT: {
605            const SkPaint& paint = fPictureData->requiredPaint(reader);
606            const SkVertices* vertices = fPictureData->getVertices(reader);
607            const int boneCount = reader->readInt();
608            (void)reader->skip(boneCount, sizeof(SkVertices_DeprecatedBone));
609            SkBlendMode bmode = reader->read32LE(SkBlendMode::kLastMode);
610            BREAK_ON_READ_ERROR(reader);
611
612            if (vertices) {  // TODO: read error if vertices == null?
613                canvas->drawVertices(vertices, bmode, paint);
614            }
615        } break;
616        case MARK_CTM: {
617            SkString name;
618            reader->readString(&name);
619            BREAK_ON_READ_ERROR(reader);
620            canvas->markCTM(name.c_str());
621        } break;
622        case RESTORE:
623            canvas->restore();
624            break;
625        case ROTATE: {
626            auto deg = reader->readScalar();
627            canvas->rotate(deg);
628        } break;
629        case SAVE:
630            canvas->save();
631            break;
632        case SAVE_BEHIND: {
633            uint32_t flags = reader->readInt();
634            const SkRect* subset = nullptr;
635            SkRect storage;
636            if (flags & SAVEBEHIND_HAS_SUBSET) {
637                reader->readRect(&storage);
638                subset = &storage;
639            }
640            SkCanvasPriv::SaveBehind(canvas, subset);
641        } break;
642        case SAVE_LAYER_SAVELAYERREC: {
643            SkCanvas::SaveLayerRec rec(nullptr, nullptr, nullptr, 0);
644            const uint32_t flatFlags = reader->readInt();
645            SkRect bounds;
646            if (flatFlags & SAVELAYERREC_HAS_BOUNDS) {
647                reader->readRect(&bounds);
648                rec.fBounds = &bounds;
649            }
650            if (flatFlags & SAVELAYERREC_HAS_PAINT) {
651                rec.fPaint = &fPictureData->requiredPaint(reader);
652            }
653            if (flatFlags & SAVELAYERREC_HAS_BACKDROP) {
654                const SkPaint& paint = fPictureData->requiredPaint(reader);
655                rec.fBackdrop = paint.getImageFilter();
656            }
657            if (flatFlags & SAVELAYERREC_HAS_FLAGS) {
658                rec.fSaveLayerFlags = reader->readInt();
659            }
660            if (flatFlags & SAVELAYERREC_HAS_CLIPMASK_OBSOLETE) {
661                (void)fPictureData->getImage(reader);
662            }
663            if (flatFlags & SAVELAYERREC_HAS_CLIPMATRIX_OBSOLETE) {
664                SkMatrix clipMatrix_ignored;
665                reader->readMatrix(&clipMatrix_ignored);
666            }
667            if (!reader->isVersionLT(SkPicturePriv::Version::kBackdropScaleFactor) &&
668                (flatFlags & SAVELAYERREC_HAS_BACKDROP_SCALE)) {
669                SkCanvasPriv::SetBackdropScaleFactor(&rec, reader->readScalar());
670            }
671            BREAK_ON_READ_ERROR(reader);
672
673            canvas->saveLayer(rec);
674        } break;
675        case SCALE: {
676            SkScalar sx = reader->readScalar();
677            SkScalar sy = reader->readScalar();
678            canvas->scale(sx, sy);
679        } break;
680        case SET_M44: {
681            SkM44 m;
682            reader->read(&m);
683            canvas->setMatrix(initialMatrix * m);
684        } break;
685        case SET_MATRIX: {
686            SkMatrix matrix;
687            reader->readMatrix(&matrix);
688            canvas->setMatrix(initialMatrix * SkM44(matrix));
689        } break;
690        case SKEW: {
691            SkScalar sx = reader->readScalar();
692            SkScalar sy = reader->readScalar();
693            canvas->skew(sx, sy);
694        } break;
695        case TRANSLATE: {
696            SkScalar dx = reader->readScalar();
697            SkScalar dy = reader->readScalar();
698            canvas->translate(dx, dy);
699        } break;
700        default:
701            reader->validate(false);    // unknown op
702            break;
703    }
704
705#undef BREAK_ON_READ_ERROR
706}
707