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