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