• 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 "SkCanvas.h"
9 #include "SkDrawShadowRec.h"
10 #include "SkPatchUtils.h"
11 #include "SkPictureData.h"
12 #include "SkPicturePlayback.h"
13 #include "SkPictureRecord.h"
14 #include "SkReadBuffer.h"
15 #include "SkRSXform.h"
16 #include "SkTextBlob.h"
17 #include "SkTDArray.h"
18 #include "SkTypes.h"
19 
20 // matches old SkCanvas::SaveFlags
21 enum LegacySaveFlags {
22     kHasAlphaLayer_LegacySaveFlags    = 0x04,
23     kClipToLayer_LegacySaveFlags      = 0x10,
24 };
25 
LegacySaveFlagsToSaveLayerFlags(uint32_t flags)26 SkCanvas::SaveLayerFlags SkCanvas::LegacySaveFlagsToSaveLayerFlags(uint32_t flags) {
27     uint32_t layerFlags = 0;
28 
29     if (0 == (flags & kClipToLayer_LegacySaveFlags)) {
30         layerFlags |= SkCanvas::kDontClipToLayer_PrivateSaveLayerFlag;
31     }
32     if (0 == (flags & kHasAlphaLayer_LegacySaveFlags)) {
33         layerFlags |= kIsOpaque_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 (((uint8_t)temp) == 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 
71 class TextContainer {
72 public:
length()73     size_t length() { return fByteLength; }
text()74     const void* text() { return (const void*)fText; }
75     size_t fByteLength;
76     const char* fText;
77 };
78 
get_text(SkReadBuffer * reader,TextContainer * text)79 void get_text(SkReadBuffer* reader, TextContainer* text) {
80     size_t length = text->fByteLength = reader->readInt();
81     text->fText = (const char*)reader->skip(length);
82 }
83 
draw(SkCanvas * canvas,SkPicture::AbortCallback * callback,SkReadBuffer * buffer)84 void SkPicturePlayback::draw(SkCanvas* canvas,
85                              SkPicture::AbortCallback* callback,
86                              SkReadBuffer* buffer) {
87     AutoResetOpID aroi(this);
88     SkASSERT(0 == fCurOffset);
89 
90     std::unique_ptr<SkReadBuffer> reader;
91     if (buffer) {
92         reader.reset(buffer->clone(fPictureData->opData()->bytes(),
93                                    fPictureData->opData()->size()));
94     } else {
95         reader.reset(new SkReadBuffer(fPictureData->opData()->bytes(),
96                                       fPictureData->opData()->size()));
97     }
98 
99     // Record this, so we can concat w/ it if we encounter a setMatrix()
100     SkMatrix initialMatrix = canvas->getTotalMatrix();
101 
102     SkAutoCanvasRestore acr(canvas, false);
103 
104     while (!reader->eof()) {
105         if (callback && callback->abort()) {
106             return;
107         }
108 
109         fCurOffset = reader->offset();
110         uint32_t size;
111         DrawType op = ReadOpAndSize(reader.get(), &size);
112         if (!reader->validate(op > UNUSED && op <= LAST_DRAWTYPE_ENUM)) {
113             return;
114         }
115 
116         this->handleOp(reader.get(), op, size, canvas, initialMatrix);
117     }
118 
119     // need to propagate invalid state to the parent reader
120     if (buffer) {
121         buffer->validate(reader->isValid());
122     }
123 }
124 
handleOp(SkReadBuffer * reader,DrawType op,uint32_t size,SkCanvas * canvas,const SkMatrix & initialMatrix)125 void SkPicturePlayback::handleOp(SkReadBuffer* reader,
126                                  DrawType op,
127                                  uint32_t size,
128                                  SkCanvas* canvas,
129                                  const SkMatrix& initialMatrix) {
130 #define BREAK_ON_READ_ERROR(r) if (!r->isValid()) { break; }
131 
132     switch (op) {
133         case NOOP: {
134             SkASSERT(size >= 4);
135             reader->skip(size - 4);
136         } break;
137         case CLIP_PATH: {
138             const SkPath& path = fPictureData->getPath(reader);
139             uint32_t packed = reader->readInt();
140             SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed);
141             bool doAA = ClipParams_unpackDoAA(packed);
142             size_t offsetToRestore = reader->readInt();
143             BREAK_ON_READ_ERROR(reader);
144 
145             SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
146             canvas->clipPath(path, clipOp, doAA);
147             if (canvas->isClipEmpty() && offsetToRestore) {
148                 reader->skip(offsetToRestore - reader->offset());
149             }
150         } break;
151         case CLIP_REGION: {
152             SkRegion region;
153             reader->readRegion(&region);
154             uint32_t packed = reader->readInt();
155             SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed);
156             size_t offsetToRestore = reader->readInt();
157             BREAK_ON_READ_ERROR(reader);
158 
159             SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
160             canvas->clipRegion(region, clipOp);
161             if (canvas->isClipEmpty() && offsetToRestore) {
162                 reader->skip(offsetToRestore - reader->offset());
163             }
164         } break;
165         case CLIP_RECT: {
166             SkRect rect;
167             reader->readRect(&rect);
168             uint32_t packed = reader->readInt();
169             SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed);
170             bool doAA = ClipParams_unpackDoAA(packed);
171             size_t offsetToRestore = reader->readInt();
172             BREAK_ON_READ_ERROR(reader);
173 
174             SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
175             canvas->clipRect(rect, clipOp, doAA);
176             if (canvas->isClipEmpty() && offsetToRestore) {
177                 reader->skip(offsetToRestore - reader->offset());
178             }
179         } break;
180         case CLIP_RRECT: {
181             SkRRect rrect;
182             reader->readRRect(&rrect);
183             uint32_t packed = reader->readInt();
184             SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed);
185             bool doAA = ClipParams_unpackDoAA(packed);
186             size_t offsetToRestore = reader->readInt();
187             BREAK_ON_READ_ERROR(reader);
188 
189             SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
190             canvas->clipRRect(rrect, clipOp, doAA);
191             if (canvas->isClipEmpty() && offsetToRestore) {
192                 reader->skip(offsetToRestore - reader->offset());
193             }
194         } break;
195         case PUSH_CULL: break;  // Deprecated, safe to ignore both push and pop.
196         case POP_CULL:  break;
197         case CONCAT: {
198             SkMatrix matrix;
199             reader->readMatrix(&matrix);
200             BREAK_ON_READ_ERROR(reader);
201 
202             canvas->concat(matrix);
203             break;
204         }
205         case DRAW_ANNOTATION: {
206             SkRect rect;
207             reader->readRect(&rect);
208             SkString key;
209             reader->readString(&key);
210             sk_sp<SkData> data = reader->readByteArrayAsData();
211             BREAK_ON_READ_ERROR(reader);
212 
213             canvas->drawAnnotation(rect, key.c_str(), data.get());
214         } break;
215         case DRAW_ARC: {
216             const SkPaint* paint = fPictureData->getPaint(reader);
217             SkRect rect;
218             reader->readRect(&rect);
219             SkScalar startAngle = reader->readScalar();
220             SkScalar sweepAngle = reader->readScalar();
221             int useCenter = reader->readInt();
222             BREAK_ON_READ_ERROR(reader);
223 
224             if (paint) {
225                 canvas->drawArc(rect, startAngle, sweepAngle, SkToBool(useCenter), *paint);
226             }
227         } break;
228         case DRAW_ATLAS: {
229             const SkPaint* paint = fPictureData->getPaint(reader);
230             const SkImage* atlas = fPictureData->getImage(reader);
231             const uint32_t flags = reader->readUInt();
232             const int count = reader->readUInt();
233             const SkRSXform* xform = (const SkRSXform*)reader->skip(count * sizeof(SkRSXform));
234             const SkRect* tex = (const SkRect*)reader->skip(count * sizeof(SkRect));
235             const SkColor* colors = nullptr;
236             SkBlendMode mode = SkBlendMode::kDst;
237             if (flags & DRAW_ATLAS_HAS_COLORS) {
238                 colors = (const SkColor*)reader->skip(count * sizeof(SkColor));
239                 mode = (SkBlendMode)reader->readUInt();
240             }
241             const SkRect* cull = nullptr;
242             if (flags & DRAW_ATLAS_HAS_CULL) {
243                 cull = (const SkRect*)reader->skip(sizeof(SkRect));
244             }
245             BREAK_ON_READ_ERROR(reader);
246 
247             canvas->drawAtlas(atlas, xform, tex, colors, count, mode, cull, paint);
248         } break;
249         case DRAW_BITMAP: {
250             const SkPaint* paint = fPictureData->getPaint(reader);
251             const SkImage* image = fPictureData->getBitmapAsImage(reader);
252             SkPoint loc;
253             reader->readPoint(&loc);
254             BREAK_ON_READ_ERROR(reader);
255 
256             canvas->drawImage(image, loc.fX, loc.fY, paint);
257         } break;
258         case DRAW_BITMAP_RECT: {
259             const SkPaint* paint = fPictureData->getPaint(reader);
260             const SkImage* image = fPictureData->getBitmapAsImage(reader);
261             SkRect storage;
262             const SkRect* src = get_rect_ptr(reader, &storage);   // may be null
263             SkRect dst;
264             reader->readRect(&dst);     // required
265             SkCanvas::SrcRectConstraint constraint = (SkCanvas::SrcRectConstraint)reader->readInt();
266             BREAK_ON_READ_ERROR(reader);
267 
268             if (src) {
269                 canvas->drawImageRect(image, *src, dst, paint, constraint);
270             } else {
271                 canvas->drawImageRect(image, dst, paint, constraint);
272             }
273         } break;
274         case DRAW_BITMAP_MATRIX: {
275             const SkPaint* paint = fPictureData->getPaint(reader);
276             const SkImage* image = fPictureData->getBitmapAsImage(reader);
277             SkMatrix matrix;
278             reader->readMatrix(&matrix);
279             BREAK_ON_READ_ERROR(reader);
280 
281             SkAutoCanvasRestore acr(canvas, true);
282             canvas->concat(matrix);
283             canvas->drawImage(image, 0, 0, paint);
284         } break;
285         case DRAW_BITMAP_NINE: {
286             const SkPaint* paint = fPictureData->getPaint(reader);
287             const SkImage* image = fPictureData->getBitmapAsImage(reader);
288             SkIRect src;
289             reader->readIRect(&src);
290             SkRect dst;
291             reader->readRect(&dst);
292             BREAK_ON_READ_ERROR(reader);
293 
294             canvas->drawImageNine(image, src, dst, paint);
295         } break;
296         case DRAW_CLEAR: {
297             auto c = reader->readInt();
298             BREAK_ON_READ_ERROR(reader);
299 
300             canvas->clear(c);
301         } break;
302         case DRAW_DATA: {
303             // This opcode is now dead, just need to skip it for backwards compatibility
304             size_t length = reader->readInt();
305             (void)reader->skip(length);
306             // skip handles padding the read out to a multiple of 4
307         } break;
308         case DRAW_DRAWABLE: {
309             auto* d = fPictureData->getDrawable(reader);
310             BREAK_ON_READ_ERROR(reader);
311 
312             canvas->drawDrawable(d);
313         } break;
314         case DRAW_DRAWABLE_MATRIX: {
315             SkMatrix matrix;
316             reader->readMatrix(&matrix);
317             SkDrawable* drawable = fPictureData->getDrawable(reader);
318             BREAK_ON_READ_ERROR(reader);
319 
320             canvas->drawDrawable(drawable, &matrix);
321         } break;
322         case DRAW_DRRECT: {
323             const SkPaint* paint = fPictureData->getPaint(reader);
324             SkRRect outer, inner;
325             reader->readRRect(&outer);
326             reader->readRRect(&inner);
327             BREAK_ON_READ_ERROR(reader);
328 
329             if (paint) {
330                 canvas->drawDRRect(outer, inner, *paint);
331             }
332         } break;
333         case BEGIN_COMMENT_GROUP: {
334             SkString tmp;
335             reader->readString(&tmp);
336             // deprecated (M44)
337             break;
338         }
339         case COMMENT: {
340             SkString tmp;
341             reader->readString(&tmp);
342             reader->readString(&tmp);
343             // deprecated (M44)
344             break;
345         }
346         case END_COMMENT_GROUP:
347             // deprecated (M44)
348             break;
349         case DRAW_IMAGE: {
350             const SkPaint* paint = fPictureData->getPaint(reader);
351             const SkImage* image = fPictureData->getImage(reader);
352             SkPoint loc;
353             reader->readPoint(&loc);
354             BREAK_ON_READ_ERROR(reader);
355 
356             canvas->drawImage(image, loc.fX, loc.fY, paint);
357         } break;
358         case DRAW_IMAGE_LATTICE: {
359             const SkPaint* paint = fPictureData->getPaint(reader);
360             const SkImage* image = fPictureData->getImage(reader);
361             SkCanvas::Lattice lattice;
362             lattice.fXCount = reader->readInt();
363             lattice.fXDivs = (const int*) reader->skip(lattice.fXCount * sizeof(int32_t));
364             lattice.fYCount = reader->readInt();
365             lattice.fYDivs = (const int*) reader->skip(lattice.fYCount * sizeof(int32_t));
366             int flagCount = reader->readInt();
367             lattice.fFlags = (0 == flagCount) ? nullptr : (const SkCanvas::Lattice::Flags*)
368                     reader->skip(SkAlign4(flagCount * sizeof(SkCanvas::Lattice::Flags)));
369             SkIRect src;
370             reader->readIRect(&src);
371             lattice.fBounds = &src;
372             SkRect dst;
373             reader->readRect(&dst);
374             BREAK_ON_READ_ERROR(reader);
375 
376             canvas->drawImageLattice(image, lattice, dst, paint);
377         } break;
378         case DRAW_IMAGE_NINE: {
379             const SkPaint* paint = fPictureData->getPaint(reader);
380             const SkImage* image = fPictureData->getImage(reader);
381             SkIRect center;
382             reader->readIRect(&center);
383             SkRect dst;
384             reader->readRect(&dst);
385             BREAK_ON_READ_ERROR(reader);
386 
387             canvas->drawImageNine(image, center, dst, paint);
388         } break;
389         case DRAW_IMAGE_RECT_STRICT:
390         case DRAW_IMAGE_RECT: {
391             const SkPaint* paint = fPictureData->getPaint(reader);
392             const SkImage* image = fPictureData->getImage(reader);
393             SkRect storage;
394             const SkRect* src = get_rect_ptr(reader, &storage);   // may be null
395             SkRect dst;
396             reader->readRect(&dst);     // required
397             // DRAW_IMAGE_RECT_STRICT assumes this constraint, and doesn't store it
398             SkCanvas::SrcRectConstraint constraint = SkCanvas::kStrict_SrcRectConstraint;
399             if (DRAW_IMAGE_RECT == op) {
400                 // newer op-code stores the constraint explicitly
401                 constraint = (SkCanvas::SrcRectConstraint)reader->readInt();
402             }
403             BREAK_ON_READ_ERROR(reader);
404 
405             canvas->legacy_drawImageRect(image, src, dst, paint, constraint);
406         } break;
407         case DRAW_OVAL: {
408             const SkPaint* paint = fPictureData->getPaint(reader);
409             SkRect rect;
410             reader->readRect(&rect);
411             BREAK_ON_READ_ERROR(reader);
412 
413             if (paint) {
414                 canvas->drawOval(rect, *paint);
415             }
416         } break;
417         case DRAW_PAINT: {
418             const SkPaint* paint = fPictureData->getPaint(reader);
419             BREAK_ON_READ_ERROR(reader);
420 
421             if (paint) {
422                 canvas->drawPaint(*paint);
423             }
424         } break;
425         case DRAW_PATCH: {
426             const SkPaint* paint = fPictureData->getPaint(reader);
427 
428             const SkPoint* cubics = (const SkPoint*)reader->skip(SkPatchUtils::kNumCtrlPts *
429                                                                  sizeof(SkPoint));
430             uint32_t flag = reader->readInt();
431             const SkColor* colors = nullptr;
432             if (flag & DRAW_VERTICES_HAS_COLORS) {
433                 colors = (const SkColor*)reader->skip(SkPatchUtils::kNumCorners * sizeof(SkColor));
434             }
435             const SkPoint* texCoords = nullptr;
436             if (flag & DRAW_VERTICES_HAS_TEXS) {
437                 texCoords = (const SkPoint*)reader->skip(SkPatchUtils::kNumCorners *
438                                                          sizeof(SkPoint));
439             }
440             SkBlendMode bmode = SkBlendMode::kModulate;
441             if (flag & DRAW_VERTICES_HAS_XFER) {
442                 unsigned mode = reader->readInt();
443                 if (mode <= (unsigned)SkBlendMode::kLastMode) {
444                     bmode = (SkBlendMode)mode;
445                 }
446             }
447             BREAK_ON_READ_ERROR(reader);
448 
449             if (paint) {
450                 canvas->drawPatch(cubics, colors, texCoords, bmode, *paint);
451             }
452         } break;
453         case DRAW_PATH: {
454             const SkPaint* paint = fPictureData->getPaint(reader);
455             const auto& path = fPictureData->getPath(reader);
456             BREAK_ON_READ_ERROR(reader);
457 
458             if (paint) {
459                 canvas->drawPath(path, *paint);
460             }
461         } break;
462         case DRAW_PICTURE: {
463             const auto* pic = fPictureData->getPicture(reader);
464             BREAK_ON_READ_ERROR(reader);
465 
466             canvas->drawPicture(pic);
467         } break;
468         case DRAW_PICTURE_MATRIX_PAINT: {
469             const SkPaint* paint = fPictureData->getPaint(reader);
470             SkMatrix matrix;
471             reader->readMatrix(&matrix);
472             const SkPicture* pic = fPictureData->getPicture(reader);
473             BREAK_ON_READ_ERROR(reader);
474 
475             canvas->drawPicture(pic, &matrix, paint);
476         } break;
477         case DRAW_POINTS: {
478             const SkPaint* paint = fPictureData->getPaint(reader);
479             SkCanvas::PointMode mode = (SkCanvas::PointMode)reader->readInt();
480             size_t count = reader->readInt();
481             const SkPoint* pts = (const SkPoint*)reader->skip(sizeof(SkPoint)* count);
482             BREAK_ON_READ_ERROR(reader);
483 
484             if (paint) {
485                 canvas->drawPoints(mode, count, pts, *paint);
486             }
487         } break;
488         case DRAW_POS_TEXT: {
489             const SkPaint* paint = fPictureData->getPaint(reader);
490             TextContainer text;
491             get_text(reader, &text);
492             size_t points = reader->readInt();
493             const SkPoint* pos = (const SkPoint*)reader->skip(points * sizeof(SkPoint));
494             BREAK_ON_READ_ERROR(reader);
495 
496             if (paint && text.text()) {
497                 canvas->drawPosText(text.text(), text.length(), pos, *paint);
498             }
499         } break;
500         case DRAW_POS_TEXT_TOP_BOTTOM: {
501             const SkPaint* paint = fPictureData->getPaint(reader);
502             TextContainer text;
503             get_text(reader, &text);
504             size_t points = reader->readInt();
505             const SkPoint* pos = (const SkPoint*)reader->skip(points * sizeof(SkPoint));
506             const SkScalar top = reader->readScalar();
507             const SkScalar bottom = reader->readScalar();
508             BREAK_ON_READ_ERROR(reader);
509 
510             SkRect clip = canvas->getLocalClipBounds();
511             if (top < clip.fBottom && bottom > clip.fTop && paint && text.text()) {
512                 canvas->drawPosText(text.text(), text.length(), pos, *paint);
513             }
514         } break;
515         case DRAW_POS_TEXT_H: {
516             const SkPaint* paint = fPictureData->getPaint(reader);
517             TextContainer text;
518             get_text(reader, &text);
519             size_t xCount = reader->readInt();
520             const SkScalar constY = reader->readScalar();
521             const SkScalar* xpos = (const SkScalar*)reader->skip(xCount * sizeof(SkScalar));
522             BREAK_ON_READ_ERROR(reader);
523 
524             if (paint && text.text()) {
525                 canvas->drawPosTextH(text.text(), text.length(), xpos, constY, *paint);
526             }
527         } break;
528         case DRAW_POS_TEXT_H_TOP_BOTTOM: {
529             const SkPaint* paint = fPictureData->getPaint(reader);
530             TextContainer text;
531             get_text(reader, &text);
532             size_t xCount = reader->readInt();
533             const SkScalar* xpos = (const SkScalar*)reader->skip((3 + xCount) * sizeof(SkScalar));
534             BREAK_ON_READ_ERROR(reader);
535 
536             const SkScalar top = *xpos++;
537             const SkScalar bottom = *xpos++;
538             const SkScalar constY = *xpos++;
539             SkRect clip = canvas->getLocalClipBounds();
540             if (top < clip.fBottom && bottom > clip.fTop && paint && text.text()) {
541                 canvas->drawPosTextH(text.text(), text.length(), xpos, constY, *paint);
542             }
543         } break;
544         case DRAW_RECT: {
545             const SkPaint* paint = fPictureData->getPaint(reader);
546             SkRect rect;
547             reader->readRect(&rect);
548             BREAK_ON_READ_ERROR(reader);
549 
550             if (paint) {
551                 canvas->drawRect(rect, *paint);
552             }
553         } break;
554         case DRAW_REGION: {
555             const SkPaint* paint = fPictureData->getPaint(reader);
556             SkRegion region;
557             reader->readRegion(&region);
558             BREAK_ON_READ_ERROR(reader);
559 
560             if (paint) {
561                 canvas->drawRegion(region, *paint);
562             }
563         } break;
564         case DRAW_RRECT: {
565             const SkPaint* paint = fPictureData->getPaint(reader);
566             SkRRect rrect;
567             reader->readRRect(&rrect);
568             BREAK_ON_READ_ERROR(reader);
569 
570             if (paint) {
571                 canvas->drawRRect(rrect, *paint);
572             }
573         } break;
574         case DRAW_SHADOW_REC: {
575             const auto& path = fPictureData->getPath(reader);
576             SkDrawShadowRec rec;
577             reader->readPoint3(&rec.fZPlaneParams);
578             reader->readPoint3(&rec.fLightPos);
579             rec.fLightRadius = reader->readScalar();
580             rec.fAmbientAlpha = reader->readScalar();
581             rec.fSpotAlpha = reader->readScalar();
582             rec.fColor = reader->read32();
583             rec.fFlags = reader->read32();
584             BREAK_ON_READ_ERROR(reader);
585 
586             canvas->private_draw_shadow_rec(path, rec);
587         } break;
588         case DRAW_SPRITE: {
589             /* const SkPaint* paint = */ fPictureData->getPaint(reader);
590             /* const SkImage* image = */ fPictureData->getBitmapAsImage(reader);
591             /* int left = */ reader->readInt();
592             /* int top = */ reader->readInt();
593             // drawSprite removed dec-2015
594         } break;
595         case DRAW_TEXT: {
596             const SkPaint* paint = fPictureData->getPaint(reader);
597             TextContainer text;
598             get_text(reader, &text);
599             SkScalar x = reader->readScalar();
600             SkScalar y = reader->readScalar();
601             BREAK_ON_READ_ERROR(reader);
602 
603             if (paint && text.text()) {
604                 canvas->drawText(text.text(), text.length(), x, y, *paint);
605             }
606         } break;
607         case DRAW_TEXT_BLOB: {
608             const SkPaint* paint = fPictureData->getPaint(reader);
609             const SkTextBlob* blob = fPictureData->getTextBlob(reader);
610             SkScalar x = reader->readScalar();
611             SkScalar y = reader->readScalar();
612             BREAK_ON_READ_ERROR(reader);
613 
614             if (paint) {
615                 canvas->drawTextBlob(blob, x, y, *paint);
616             }
617         } break;
618         case DRAW_TEXT_TOP_BOTTOM: {
619             const SkPaint* paint = fPictureData->getPaint(reader);
620             TextContainer text;
621             get_text(reader, &text);
622             const SkScalar* ptr = (const SkScalar*)reader->skip(4 * sizeof(SkScalar));
623             BREAK_ON_READ_ERROR(reader);
624 
625             // ptr[0] == x
626             // ptr[1] == y
627             // ptr[2] == top
628             // ptr[3] == bottom
629             SkRect clip = canvas->getLocalClipBounds();
630             float top = ptr[2];
631             float bottom = ptr[3];
632             if (top < clip.fBottom && bottom > clip.fTop && paint && text.text()) {
633                 canvas->drawText(text.text(), text.length(), ptr[0], ptr[1], *paint);
634             }
635         } break;
636         case DRAW_TEXT_ON_PATH: {
637             const SkPaint* paint = fPictureData->getPaint(reader);
638             TextContainer text;
639             get_text(reader, &text);
640             const SkPath& path = fPictureData->getPath(reader);
641             SkMatrix matrix;
642             reader->readMatrix(&matrix);
643             BREAK_ON_READ_ERROR(reader);
644 
645             if (paint && text.text()) {
646                 canvas->drawTextOnPath(text.text(), text.length(), path, &matrix, *paint);
647             }
648         } break;
649         case DRAW_TEXT_RSXFORM: {
650             const SkPaint* paint = fPictureData->getPaint(reader);
651             int count = reader->readInt();
652             uint32_t flags = reader->read32();
653             TextContainer text;
654             get_text(reader, &text);
655             const SkRSXform* xform = (const SkRSXform*)reader->skip(count * sizeof(SkRSXform));
656             const SkRect* cull = nullptr;
657             if (flags & DRAW_TEXT_RSXFORM_HAS_CULL) {
658                 cull = (const SkRect*)reader->skip(sizeof(SkRect));
659             }
660             BREAK_ON_READ_ERROR(reader);
661 
662             if (text.text()) {
663                 canvas->drawTextRSXform(text.text(), text.length(), xform, cull, *paint);
664             }
665         } break;
666         case DRAW_VERTICES_RETIRED_03_2017: {
667             const SkPaint* paint = fPictureData->getPaint(reader);
668             DrawVertexFlags flags = (DrawVertexFlags)reader->readInt();
669             SkVertices::VertexMode vmode = (SkVertices::VertexMode)reader->readInt();
670             int vCount = reader->readInt();
671             const SkPoint* verts = (const SkPoint*)reader->skip(vCount * sizeof(SkPoint));
672             const SkPoint* texs = nullptr;
673             const SkColor* colors = nullptr;
674             const uint16_t* indices = nullptr;
675             int iCount = 0;
676             if (flags & DRAW_VERTICES_HAS_TEXS) {
677                 texs = (const SkPoint*)reader->skip(vCount * sizeof(SkPoint));
678             }
679             if (flags & DRAW_VERTICES_HAS_COLORS) {
680                 colors = (const SkColor*)reader->skip(vCount * sizeof(SkColor));
681             }
682             if (flags & DRAW_VERTICES_HAS_INDICES) {
683                 iCount = reader->readInt();
684                 indices = (const uint16_t*)reader->skip(iCount * sizeof(uint16_t));
685             }
686             SkBlendMode bmode = SkBlendMode::kModulate;
687             if (flags & DRAW_VERTICES_HAS_XFER) {
688                 unsigned mode = reader->readInt();
689                 if (mode <= (unsigned)SkBlendMode::kLastMode) {
690                     bmode = (SkBlendMode)mode;
691                 }
692             }
693             BREAK_ON_READ_ERROR(reader);
694 
695             if (paint) {
696                 canvas->drawVertices(SkVertices::MakeCopy(vmode, vCount, verts, texs, colors,
697                                                           iCount, indices), bmode, *paint);
698             }
699         } break;
700         case DRAW_VERTICES_OBJECT: {
701             const SkPaint* paint = fPictureData->getPaint(reader);
702             const SkVertices* vertices = fPictureData->getVertices(reader);
703             SkBlendMode bmode = static_cast<SkBlendMode>(reader->readInt());
704 
705             BREAK_ON_READ_ERROR(reader);
706 
707             if (paint && vertices) {
708                 canvas->drawVertices(vertices, bmode, *paint);
709             }
710         } break;
711         case RESTORE:
712             canvas->restore();
713             break;
714         case ROTATE: {
715             auto deg = reader->readScalar();
716             BREAK_ON_READ_ERROR(reader);
717 
718             canvas->rotate(deg);
719         } break;
720         case SAVE:
721             canvas->save();
722             break;
723         case SAVE_LAYER_SAVEFLAGS_DEPRECATED: {
724             SkRect storage;
725             const SkRect* boundsPtr = get_rect_ptr(reader, &storage);
726             const SkPaint* paint = fPictureData->getPaint(reader);
727             auto flags = SkCanvas::LegacySaveFlagsToSaveLayerFlags(reader->readInt());
728             BREAK_ON_READ_ERROR(reader);
729 
730             canvas->saveLayer(SkCanvas::SaveLayerRec(boundsPtr, paint, flags));
731         } break;
732         case SAVE_LAYER_SAVELAYERFLAGS_DEPRECATED_JAN_2016: {
733             SkRect storage;
734             const SkRect* boundsPtr = get_rect_ptr(reader, &storage);
735             const SkPaint* paint = fPictureData->getPaint(reader);
736             auto flags = reader->readInt();
737             BREAK_ON_READ_ERROR(reader);
738 
739             canvas->saveLayer(SkCanvas::SaveLayerRec(boundsPtr, paint, flags));
740         } break;
741         case SAVE_LAYER_SAVELAYERREC: {
742             SkCanvas::SaveLayerRec rec(nullptr, nullptr, nullptr, nullptr, nullptr, 0);
743             SkMatrix clipMatrix;
744             const uint32_t flatFlags = reader->readInt();
745             SkRect bounds;
746             if (flatFlags & SAVELAYERREC_HAS_BOUNDS) {
747                 reader->readRect(&bounds);
748                 rec.fBounds = &bounds;
749             }
750             if (flatFlags & SAVELAYERREC_HAS_PAINT) {
751                 rec.fPaint = fPictureData->getPaint(reader);
752             }
753             if (flatFlags & SAVELAYERREC_HAS_BACKDROP) {
754                 if (const auto* paint = fPictureData->getPaint(reader)) {
755                     rec.fBackdrop = paint->getImageFilter();
756                 }
757             }
758             if (flatFlags & SAVELAYERREC_HAS_FLAGS) {
759                 rec.fSaveLayerFlags = reader->readInt();
760             }
761             if (flatFlags & SAVELAYERREC_HAS_CLIPMASK) {
762                 rec.fClipMask = fPictureData->getImage(reader);
763             }
764             if (flatFlags & SAVELAYERREC_HAS_CLIPMATRIX) {
765                 reader->readMatrix(&clipMatrix);
766                 rec.fClipMatrix = &clipMatrix;
767             }
768             BREAK_ON_READ_ERROR(reader);
769 
770             canvas->saveLayer(rec);
771         } break;
772         case SCALE: {
773             SkScalar sx = reader->readScalar();
774             SkScalar sy = reader->readScalar();
775             BREAK_ON_READ_ERROR(reader);
776 
777             canvas->scale(sx, sy);
778         } break;
779         case SET_MATRIX: {
780             SkMatrix matrix;
781             reader->readMatrix(&matrix);
782             BREAK_ON_READ_ERROR(reader);
783 
784             matrix.postConcat(initialMatrix);
785             canvas->setMatrix(matrix);
786         } break;
787         case SKEW: {
788             SkScalar sx = reader->readScalar();
789             SkScalar sy = reader->readScalar();
790             BREAK_ON_READ_ERROR(reader);
791 
792             canvas->skew(sx, sy);
793         } break;
794         case TRANSLATE: {
795             SkScalar dx = reader->readScalar();
796             SkScalar dy = reader->readScalar();
797             BREAK_ON_READ_ERROR(reader);
798 
799             canvas->translate(dx, dy);
800         } break;
801         default:
802             SkASSERTF(false, "Unknown draw type: %d", op);
803     }
804 
805 #undef BREAK_ON_READ_ERROR
806 }
807