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