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