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