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