• 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/SkImageFilter.h"
16 #include "include/core/SkMatrix.h"
17 #include "include/core/SkPaint.h"
18 #include "include/core/SkPoint.h"
19 #include "include/core/SkRRect.h"
20 #include "include/core/SkRSXform.h"
21 #include "include/core/SkRect.h"
22 #include "include/core/SkRefCnt.h"
23 #include "include/core/SkRegion.h"
24 #include "include/core/SkSamplingOptions.h"
25 #include "include/core/SkScalar.h"
26 #include "include/core/SkString.h"
27 #include "include/core/SkTypes.h"
28 #include "include/private/base/SkAlign.h"
29 #include "include/private/base/SkTArray.h"
30 #include "include/private/base/SkTemplates.h"
31 #include "include/private/base/SkTo.h"
32 #include "src/base/SkSafeMath.h"
33 #include "src/core/SkCanvasPriv.h"
34 #include "src/core/SkDrawShadowInfo.h"
35 #include "src/core/SkPictureData.h"
36 #include "src/core/SkPictureFlat.h"
37 #include "src/core/SkPicturePriv.h"
38 #include "src/core/SkReadBuffer.h"
39 #include "src/core/SkVerticesPriv.h"
40 #include "src/utils/SkPatchUtils.h"
41 
42 class SkDrawable;
43 class SkPath;
44 class SkTextBlob;
45 class SkVertices;
46 
47 namespace sktext { namespace gpu { class Slug; } }
48 
49 using namespace skia_private;
50 
get_rect_ptr(SkReadBuffer * reader,SkRect * storage)51 static const SkRect* get_rect_ptr(SkReadBuffer* reader, SkRect* storage) {
52     if (reader->readBool()) {
53         reader->readRect(storage);
54         return storage;
55     } else {
56         return nullptr;
57     }
58 }
59 
draw(SkCanvas * canvas,SkPicture::AbortCallback * callback,SkReadBuffer * buffer)60 void SkPicturePlayback::draw(SkCanvas* canvas,
61                              SkPicture::AbortCallback* callback,
62                              SkReadBuffer* buffer) {
63     AutoResetOpID aroi(this);
64     SkASSERT(0 == fCurOffset);
65 
66     SkReadBuffer reader(fPictureData->opData()->bytes(),
67                         fPictureData->opData()->size());
68     reader.setVersion(fPictureData->info().getVersion());
69 
70     // Record this, so we can concat w/ it if we encounter a setMatrix()
71     SkM44 initialMatrix = canvas->getLocalToDevice();
72 
73     SkAutoCanvasRestore acr(canvas, false);
74 
75     while (!reader.eof() && reader.isValid()) {
76         if (callback && callback->abort()) {
77             return;
78         }
79 
80         fCurOffset = reader.offset();
81 
82         uint32_t bits = reader.readInt();
83         uint32_t op   = bits >> 24,
84                  size = bits & 0xffffff;
85         if (size == 0xffffff) {
86             size = reader.readInt();
87         }
88 
89         if (!reader.validate(size > 0 && op > UNUSED && op <= LAST_DRAWTYPE_ENUM)) {
90             return;
91         }
92 
93         this->handleOp(&reader, (DrawType)op, size, canvas, initialMatrix);
94     }
95 
96     // need to propagate invalid state to the parent reader
97     if (buffer) {
98         buffer->validate(reader.isValid());
99     }
100 }
101 
validate_offsetToRestore(SkReadBuffer * reader,size_t offsetToRestore)102 static void validate_offsetToRestore(SkReadBuffer* reader, size_t offsetToRestore) {
103     if (offsetToRestore) {
104         reader->validate(SkIsAlign4(offsetToRestore) && offsetToRestore >= reader->offset());
105     }
106 }
107 
do_clip_op(SkReadBuffer * reader,SkCanvas * canvas,SkRegion::Op op,SkClipOp * clipOpToUse)108 static bool do_clip_op(SkReadBuffer* reader, SkCanvas* canvas, SkRegion::Op op,
109                        SkClipOp* clipOpToUse) {
110     switch(op) {
111         case SkRegion::kDifference_Op:
112         case SkRegion::kIntersect_Op:
113             // Fully supported, identity mapping between SkClipOp and Region::Op
114             *clipOpToUse = static_cast<SkClipOp>(op);
115             return true;
116         case SkRegion::kReplace_Op:
117             // Emulate the replace by resetting first and following it up with an intersect
118             SkASSERT(reader->isVersionLT(SkPicturePriv::kNoExpandingClipOps));
119             SkCanvasPriv::ResetClip(canvas);
120             *clipOpToUse = SkClipOp::kIntersect;
121             return true;
122         default:
123             // An expanding clip op, which if encountered on an old SKP, we just silently ignore
124             SkASSERT(reader->isVersionLT(SkPicturePriv::kNoExpandingClipOps));
125             return false;
126     }
127 }
128 
handleOp(SkReadBuffer * reader,DrawType op,uint32_t size,SkCanvas * canvas,const SkM44 & initialMatrix)129 void SkPicturePlayback::handleOp(SkReadBuffer* reader,
130                                  DrawType op,
131                                  uint32_t size,
132                                  SkCanvas* canvas,
133                                  const SkM44& initialMatrix) {
134 #define BREAK_ON_READ_ERROR(r)  if (!r->isValid()) break
135 
136     switch (op) {
137         case NOOP: {
138             SkASSERT(size >= 4);
139             reader->skip(size - 4);
140         } break;
141         case FLUSH:
142             break;
143         case CLIP_PATH: {
144             const SkPath& path = fPictureData->getPath(reader);
145             uint32_t packed = reader->readInt();
146             SkRegion::Op rgnOp = ClipParams_unpackRegionOp(reader, packed);
147             bool doAA = ClipParams_unpackDoAA(packed);
148             size_t offsetToRestore = reader->readInt();
149             validate_offsetToRestore(reader, offsetToRestore);
150             BREAK_ON_READ_ERROR(reader);
151 
152             SkClipOp clipOp;
153             if (do_clip_op(reader, canvas, rgnOp, &clipOp)) {
154                 canvas->clipPath(path, clipOp, doAA);
155             }
156             if (canvas->isClipEmpty() && offsetToRestore) {
157                 reader->skip(offsetToRestore - reader->offset());
158             }
159         } break;
160         case CLIP_REGION: {
161             SkRegion region;
162             reader->readRegion(&region);
163             uint32_t packed = reader->readInt();
164             SkRegion::Op rgnOp = ClipParams_unpackRegionOp(reader, packed);
165             size_t offsetToRestore = reader->readInt();
166             validate_offsetToRestore(reader, offsetToRestore);
167             BREAK_ON_READ_ERROR(reader);
168 
169             SkClipOp clipOp;
170             if (do_clip_op(reader, canvas, rgnOp, &clipOp)) {
171                 canvas->clipRegion(region, clipOp);
172             }
173             if (canvas->isClipEmpty() && offsetToRestore) {
174                 reader->skip(offsetToRestore - reader->offset());
175             }
176         } break;
177         case CLIP_RECT: {
178             SkRect rect;
179             reader->readRect(&rect);
180             uint32_t packed = reader->readInt();
181             SkRegion::Op rgnOp = ClipParams_unpackRegionOp(reader, packed);
182             bool doAA = ClipParams_unpackDoAA(packed);
183             size_t offsetToRestore = reader->readInt();
184             validate_offsetToRestore(reader, offsetToRestore);
185             BREAK_ON_READ_ERROR(reader);
186 
187             SkClipOp clipOp;
188             if (do_clip_op(reader, canvas, rgnOp, &clipOp)) {
189                 canvas->clipRect(rect, clipOp, doAA);
190             }
191             if (canvas->isClipEmpty() && offsetToRestore) {
192                 reader->skip(offsetToRestore - reader->offset());
193             }
194         } break;
195         case CLIP_RRECT: {
196             SkRRect rrect;
197             reader->readRRect(&rrect);
198             uint32_t packed = reader->readInt();
199             SkRegion::Op rgnOp = ClipParams_unpackRegionOp(reader, packed);
200             bool doAA = ClipParams_unpackDoAA(packed);
201             size_t offsetToRestore = reader->readInt();
202             validate_offsetToRestore(reader, offsetToRestore);
203             BREAK_ON_READ_ERROR(reader);
204 
205             SkClipOp clipOp;
206             if (do_clip_op(reader, canvas, rgnOp, &clipOp)) {
207                 canvas->clipRRect(rrect, clipOp, doAA);
208             }
209             if (canvas->isClipEmpty() && offsetToRestore) {
210                 reader->skip(offsetToRestore - reader->offset());
211             }
212         } break;
213         case CLIP_SHADER_IN_PAINT: {
214             const SkPaint& paint = fPictureData->requiredPaint(reader);
215             // clipShader() was never used in conjunction with deprecated, expanding clip ops, so
216             // it requires the op to just be intersect or difference.
217             SkClipOp clipOp = reader->checkRange(SkClipOp::kDifference, SkClipOp::kIntersect);
218             BREAK_ON_READ_ERROR(reader);
219 
220             canvas->clipShader(paint.refShader(), clipOp);
221         } break;
222         case RESET_CLIP:
223             // For Android, an emulated "replace" clip op appears as a manual reset followed by
224             // an intersect operation (equivalent to the above handling of replace ops encountered
225             // in old serialized pictures).
226             SkCanvasPriv::ResetClip(canvas);
227             break;
228         case PUSH_CULL: break;  // Deprecated, safe to ignore both push and pop.
229         case POP_CULL:  break;
230         case CONCAT: {
231             SkMatrix matrix;
232             reader->readMatrix(&matrix);
233             BREAK_ON_READ_ERROR(reader);
234 
235             canvas->concat(matrix);
236             break;
237         }
238         case CONCAT44: {
239             const SkScalar* colMaj = reader->skipT<SkScalar>(16);
240             BREAK_ON_READ_ERROR(reader);
241             canvas->concat(SkM44::ColMajor(colMaj));
242             break;
243         }
244         case DRAW_ANNOTATION: {
245             SkRect rect;
246             reader->readRect(&rect);
247             SkString key;
248             reader->readString(&key);
249             sk_sp<SkData> data = reader->readByteArrayAsData();
250             BREAK_ON_READ_ERROR(reader);
251             SkASSERT(data);
252 
253             canvas->drawAnnotation(rect, key.c_str(), data.get());
254         } break;
255         case DRAW_ARC: {
256             const SkPaint& paint = fPictureData->requiredPaint(reader);
257             SkRect rect;
258             reader->readRect(&rect);
259             SkScalar startAngle = reader->readScalar();
260             SkScalar sweepAngle = reader->readScalar();
261             int useCenter = reader->readInt();
262             BREAK_ON_READ_ERROR(reader);
263 
264             canvas->drawArc(rect, startAngle, sweepAngle, SkToBool(useCenter), paint);
265         } break;
266         case DRAW_ATLAS: {
267             const SkPaint* paint = fPictureData->optionalPaint(reader);
268             const SkImage* atlas = fPictureData->getImage(reader);
269             const uint32_t flags = reader->readUInt();
270             const int count = reader->readUInt();
271             const SkRSXform* xform = (const SkRSXform*)reader->skip(count, sizeof(SkRSXform));
272             const SkRect* tex = (const SkRect*)reader->skip(count, sizeof(SkRect));
273             const SkColor* colors = nullptr;
274             SkBlendMode mode = SkBlendMode::kDst;
275             if (flags & DRAW_ATLAS_HAS_COLORS) {
276                 colors = (const SkColor*)reader->skip(count, sizeof(SkColor));
277                 mode = reader->read32LE(SkBlendMode::kLastMode);
278                 BREAK_ON_READ_ERROR(reader);
279             }
280             const SkRect* cull = nullptr;
281             if (flags & DRAW_ATLAS_HAS_CULL) {
282                 cull = (const SkRect*)reader->skip(sizeof(SkRect));
283             }
284             BREAK_ON_READ_ERROR(reader);
285 
286             SkSamplingOptions sampling;
287             if (flags & DRAW_ATLAS_HAS_SAMPLING) {
288                 sampling = reader->readSampling();
289                 BREAK_ON_READ_ERROR(reader);
290             }
291             canvas->drawAtlas(atlas, xform, tex, colors, count, mode, sampling, cull, paint);
292         } break;
293         case DRAW_CLEAR: {
294             auto c = reader->readInt();
295             BREAK_ON_READ_ERROR(reader);
296 
297             canvas->clear(c);
298         } break;
299         case DRAW_DATA: {
300             // This opcode is now dead, just need to skip it for backwards compatibility
301             size_t length = reader->readInt();
302             (void)reader->skip(length);
303             // skip handles padding the read out to a multiple of 4
304         } break;
305         case DRAW_DRAWABLE: {
306             auto* d = fPictureData->getDrawable(reader);
307             BREAK_ON_READ_ERROR(reader);
308 
309             canvas->drawDrawable(d);
310         } break;
311         case DRAW_DRAWABLE_MATRIX: {
312             SkMatrix matrix;
313             reader->readMatrix(&matrix);
314             SkDrawable* drawable = fPictureData->getDrawable(reader);
315             BREAK_ON_READ_ERROR(reader);
316 
317             canvas->drawDrawable(drawable, &matrix);
318         } break;
319         case DRAW_DRRECT: {
320             const SkPaint& paint = fPictureData->requiredPaint(reader);
321             SkRRect outer, inner;
322             reader->readRRect(&outer);
323             reader->readRRect(&inner);
324             BREAK_ON_READ_ERROR(reader);
325 
326             canvas->drawDRRect(outer, inner, paint);
327         } break;
328         case DRAW_EDGEAA_QUAD: {
329             SkRect rect;
330             reader->readRect(&rect);
331             SkCanvas::QuadAAFlags aaFlags = static_cast<SkCanvas::QuadAAFlags>(reader->read32());
332             SkColor4f color;
333             reader->readColor4f(&color);
334             SkBlendMode blend = reader->read32LE(SkBlendMode::kLastMode);
335             BREAK_ON_READ_ERROR(reader);
336             bool hasClip = reader->readInt();
337             const SkPoint* clip = nullptr;
338             if (hasClip) {
339                 clip = (const SkPoint*) reader->skip(4, sizeof(SkPoint));
340             }
341             BREAK_ON_READ_ERROR(reader);
342             canvas->experimental_DrawEdgeAAQuad(rect, clip, aaFlags, color, blend);
343         } break;
344         case DRAW_EDGEAA_IMAGE_SET:
345         case DRAW_EDGEAA_IMAGE_SET2: {
346             static const size_t kEntryReadSize =
347                     4 * sizeof(uint32_t) + 2 * sizeof(SkRect) + sizeof(SkScalar);
348             static const size_t kMatrixSize = 9 * sizeof(SkScalar); // != sizeof(SkMatrix)
349 
350             int cnt = reader->readInt();
351             if (!reader->validate(cnt >= 0)) {
352                 break;
353             }
354             const SkPaint* paint = fPictureData->optionalPaint(reader);
355 
356             SkSamplingOptions sampling;
357             if (op == DRAW_EDGEAA_IMAGE_SET2) {
358                 sampling = reader->readSampling();
359             } else {
360                 sampling = SkSamplingOptions(SkFilterMode::kNearest);
361             }
362 
363             SkCanvas::SrcRectConstraint constraint =
364                     reader->checkRange(SkCanvas::kStrict_SrcRectConstraint,
365                                        SkCanvas::kFast_SrcRectConstraint);
366 
367             if (!reader->validate(SkSafeMath::Mul(cnt, kEntryReadSize) <= reader->available())) {
368                 break;
369             }
370 
371             // Track minimum necessary clip points and matrices that must be provided to satisfy
372             // the entries.
373             int expectedClipPointCount = 0;
374             int maxMatrixIndex = -1;
375             AutoTArray<SkCanvas::ImageSetEntry> set(cnt);
376             for (int i = 0; i < cnt && reader->isValid(); ++i) {
377                 set[i].fImage = sk_ref_sp(fPictureData->getImage(reader));
378                 reader->readRect(&set[i].fSrcRect);
379                 reader->readRect(&set[i].fDstRect);
380                 set[i].fMatrixIndex = reader->readInt();
381                 set[i].fAlpha = reader->readScalar();
382                 set[i].fAAFlags = reader->readUInt();
383                 set[i].fHasClip = reader->readInt();
384 
385                 expectedClipPointCount += set[i].fHasClip ? 4 : 0; // 4 points per clip quad
386                 if (set[i].fMatrixIndex > maxMatrixIndex) {
387                     maxMatrixIndex = set[i].fMatrixIndex;
388                 }
389             }
390 
391             int dstClipPointCount = reader->readInt();
392             const SkPoint* dstClips = nullptr;
393             if (!reader->validate(dstClipPointCount >= 0) ||
394                 !reader->validate(expectedClipPointCount == dstClipPointCount)) {
395                 // A bad dstClipCount (either negative, or not enough to satisfy entries).
396                 // Use exact comparison; the serialized SKP should only have included the exact
397                 // amount used by the recorded draw, even if the original array was larger.
398                 break;
399             } else if (dstClipPointCount > 0) {
400                 dstClips = (const SkPoint*) reader->skip(dstClipPointCount, 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             TArray<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             const SkPaint& paint = fPictureData->requiredPaint(reader);
637             const sktext::gpu::Slug* slug = fPictureData->getSlug(reader);
638             BREAK_ON_READ_ERROR(reader);
639 
640             canvas->drawSlug(slug, paint);
641         } break;
642         case DRAW_VERTICES_OBJECT: {
643             const SkPaint& paint = fPictureData->requiredPaint(reader);
644             const SkVertices* vertices = fPictureData->getVertices(reader);
645             const int boneCount = reader->readInt();
646             (void)reader->skip(boneCount, sizeof(SkVertices_DeprecatedBone));
647             SkBlendMode bmode = reader->read32LE(SkBlendMode::kLastMode);
648             BREAK_ON_READ_ERROR(reader);
649 
650             if (vertices) {  // TODO: read error if vertices == null?
651                 canvas->drawVertices(vertices, bmode, paint);
652             }
653         } break;
654         case RESTORE:
655             canvas->restore();
656             break;
657         case ROTATE: {
658             auto deg = reader->readScalar();
659             canvas->rotate(deg);
660         } break;
661         case SAVE:
662             canvas->save();
663             break;
664         case SAVE_BEHIND: {
665             uint32_t flags = reader->readInt();
666             const SkRect* subset = nullptr;
667             SkRect storage;
668             if (flags & SAVEBEHIND_HAS_SUBSET) {
669                 reader->readRect(&storage);
670                 subset = &storage;
671             }
672             SkCanvasPriv::SaveBehind(canvas, subset);
673         } break;
674         case SAVE_LAYER_SAVELAYERREC: {
675             SkCanvas::SaveLayerRec rec(nullptr, nullptr, nullptr, 0);
676             const uint32_t flatFlags = reader->readInt();
677             SkRect bounds;
678             skia_private::AutoSTArray<2, sk_sp<SkImageFilter>> filters;
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             if (!reader->isVersionLT(SkPicturePriv::Version::kMultipleFiltersOnSaveLayer) &&
705                 (flatFlags & SAVELAYERREC_HAS_MULTIPLE_FILTERS)) {
706                 int filterCount = reader->readUInt();
707                 reader->validate(filterCount > 0 && filterCount <= SkCanvas::kMaxFiltersPerLayer);
708                 BREAK_ON_READ_ERROR(reader);
709                 filters.reset(filterCount);
710                 for (int i = 0; i < filterCount; ++i) {
711                     const SkPaint& paint = fPictureData->requiredPaint(reader);
712                     filters[i] = paint.refImageFilter();
713                 }
714                 rec.fFilters = filters;
715             }
716             BREAK_ON_READ_ERROR(reader);
717 
718             canvas->saveLayer(rec);
719         } break;
720         case SCALE: {
721             SkScalar sx = reader->readScalar();
722             SkScalar sy = reader->readScalar();
723             canvas->scale(sx, sy);
724         } break;
725         case SET_M44: {
726             SkM44 m;
727             reader->read(&m);
728             canvas->setMatrix(initialMatrix * m);
729         } break;
730         case SET_MATRIX: {
731             SkMatrix matrix;
732             reader->readMatrix(&matrix);
733             canvas->setMatrix(initialMatrix * SkM44(matrix));
734         } break;
735         case SKEW: {
736             SkScalar sx = reader->readScalar();
737             SkScalar sy = reader->readScalar();
738             canvas->skew(sx, sy);
739         } break;
740         case TRANSLATE: {
741             SkScalar dx = reader->readScalar();
742             SkScalar dy = reader->readScalar();
743             canvas->translate(dx, dy);
744         } break;
745         default:
746             reader->validate(false);    // unknown op
747             break;
748     }
749 
750 #undef BREAK_ON_READ_ERROR
751 }
752