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