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 "SkReader32.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(SkReader32 * reader,uint32_t * size)44 DrawType SkPicturePlayback::ReadOpAndSize(SkReader32* 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(SkReader32 * reader)61 static const SkRect* get_rect_ptr(SkReader32* reader) {
62     if (reader->readBool()) {
63         return &reader->skipT<SkRect>();
64     } else {
65         return nullptr;
66     }
67 }
68 
69 class TextContainer {
70 public:
length()71     size_t length() { return fByteLength; }
text()72     const void* text() { return (const void*)fText; }
73     size_t fByteLength;
74     const char* fText;
75 };
76 
get_text(SkReader32 * reader,TextContainer * text)77 void get_text(SkReader32* reader, TextContainer* text) {
78     size_t length = text->fByteLength = reader->readInt();
79     text->fText = (const char*)reader->skip(length);
80 }
81 
82 // FIXME: SkBitmaps are stateful, so we need to copy them to play back in multiple threads.
shallow_copy(const SkBitmap & bitmap)83 static SkBitmap shallow_copy(const SkBitmap& bitmap) {
84     return bitmap;
85 }
86 
draw(SkCanvas * canvas,SkPicture::AbortCallback * callback)87 void SkPicturePlayback::draw(SkCanvas* canvas, SkPicture::AbortCallback* callback) {
88     AutoResetOpID aroi(this);
89     SkASSERT(0 == fCurOffset);
90 
91     SkReader32 reader(fPictureData->opData()->bytes(), fPictureData->opData()->size());
92 
93     // Record this, so we can concat w/ it if we encounter a setMatrix()
94     SkMatrix initialMatrix = canvas->getTotalMatrix();
95 
96     SkAutoCanvasRestore acr(canvas, false);
97 
98     while (!reader.eof()) {
99         if (callback && callback->abort()) {
100             return;
101         }
102 
103         fCurOffset = reader.offset();
104         uint32_t size;
105         DrawType op = ReadOpAndSize(&reader, &size);
106 
107         this->handleOp(&reader, op, size, canvas, initialMatrix);
108     }
109 }
110 
handleOp(SkReader32 * reader,DrawType op,uint32_t size,SkCanvas * canvas,const SkMatrix & initialMatrix)111 void SkPicturePlayback::handleOp(SkReader32* reader,
112                                  DrawType op,
113                                  uint32_t size,
114                                  SkCanvas* canvas,
115                                  const SkMatrix& initialMatrix) {
116     switch (op) {
117         case NOOP: {
118             SkASSERT(size >= 4);
119             reader->skip(size - 4);
120         } break;
121         case CLIP_PATH: {
122             const SkPath& path = fPictureData->getPath(reader);
123             uint32_t packed = reader->readInt();
124             SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
125             bool doAA = ClipParams_unpackDoAA(packed);
126             size_t offsetToRestore = reader->readInt();
127             SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
128             canvas->clipPath(path, regionOp, doAA);
129             if (canvas->isClipEmpty() && offsetToRestore) {
130                 reader->setOffset(offsetToRestore);
131             }
132         } break;
133         case CLIP_REGION: {
134             SkRegion region;
135             reader->readRegion(&region);
136             uint32_t packed = reader->readInt();
137             SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
138             size_t offsetToRestore = reader->readInt();
139             SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
140             canvas->clipRegion(region, regionOp);
141             if (canvas->isClipEmpty() && offsetToRestore) {
142                 reader->setOffset(offsetToRestore);
143             }
144         } break;
145         case CLIP_RECT: {
146             const SkRect& rect = reader->skipT<SkRect>();
147             uint32_t packed = reader->readInt();
148             SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
149             bool doAA = ClipParams_unpackDoAA(packed);
150             size_t offsetToRestore = reader->readInt();
151             SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
152             canvas->clipRect(rect, regionOp, doAA);
153             if (canvas->isClipEmpty() && offsetToRestore) {
154                 reader->setOffset(offsetToRestore);
155             }
156         } break;
157         case CLIP_RRECT: {
158             SkRRect rrect;
159             reader->readRRect(&rrect);
160             uint32_t packed = reader->readInt();
161             SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
162             bool doAA = ClipParams_unpackDoAA(packed);
163             size_t offsetToRestore = reader->readInt();
164             SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
165             canvas->clipRRect(rrect, regionOp, doAA);
166             if (canvas->isClipEmpty() && offsetToRestore) {
167                 reader->setOffset(offsetToRestore);
168             }
169         } break;
170         case PUSH_CULL: break;  // Deprecated, safe to ignore both push and pop.
171         case POP_CULL:  break;
172         case CONCAT: {
173             SkMatrix matrix;
174             reader->readMatrix(&matrix);
175             canvas->concat(matrix);
176             break;
177         }
178         case DRAW_ATLAS: {
179             const SkPaint* paint = fPictureData->getPaint(reader);
180             const SkImage* atlas = fPictureData->getImage(reader);
181             const uint32_t flags = reader->readU32();
182             const int count = reader->readU32();
183             const SkRSXform* xform = (const SkRSXform*)reader->skip(count * sizeof(SkRSXform));
184             const SkRect* tex = (const SkRect*)reader->skip(count * sizeof(SkRect));
185             const SkColor* colors = nullptr;
186             SkXfermode::Mode mode = SkXfermode::kDst_Mode;
187             if (flags & DRAW_ATLAS_HAS_COLORS) {
188                 colors = (const SkColor*)reader->skip(count * sizeof(SkColor));
189                 mode = (SkXfermode::Mode)reader->readU32();
190             }
191             const SkRect* cull = nullptr;
192             if (flags & DRAW_ATLAS_HAS_CULL) {
193                 cull = (const SkRect*)reader->skip(sizeof(SkRect));
194             }
195             canvas->drawAtlas(atlas, xform, tex, colors, count, mode, cull, paint);
196         } break;
197         case DRAW_BITMAP: {
198             const SkPaint* paint = fPictureData->getPaint(reader);
199             const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
200             const SkPoint& loc = reader->skipT<SkPoint>();
201             canvas->drawBitmap(bitmap, loc.fX, loc.fY, paint);
202         } break;
203         case DRAW_BITMAP_RECT: {
204             const SkPaint* paint = fPictureData->getPaint(reader);
205             const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
206             const SkRect* src = get_rect_ptr(reader);   // may be null
207             const SkRect& dst = reader->skipT<SkRect>();     // required
208             SkCanvas::SrcRectConstraint constraint = (SkCanvas::SrcRectConstraint)reader->readInt();
209             canvas->legacy_drawBitmapRect(bitmap, src, dst, paint, constraint);
210         } break;
211         case DRAW_BITMAP_MATRIX: {
212             const SkPaint* paint = fPictureData->getPaint(reader);
213             const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
214             SkMatrix matrix;
215             reader->readMatrix(&matrix);
216 
217             SkAutoCanvasRestore acr(canvas, true);
218             canvas->concat(matrix);
219             canvas->drawBitmap(bitmap, 0, 0, paint);
220         } break;
221         case DRAW_BITMAP_NINE: {
222             const SkPaint* paint = fPictureData->getPaint(reader);
223             const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
224             const SkIRect& src = reader->skipT<SkIRect>();
225             const SkRect& dst = reader->skipT<SkRect>();
226             canvas->drawBitmapNine(bitmap, src, dst, paint);
227         } break;
228         case DRAW_CLEAR:
229             canvas->clear(reader->readInt());
230             break;
231         case DRAW_DATA: {
232             // This opcode is now dead, just need to skip it for backwards compatibility
233             size_t length = reader->readInt();
234             (void)reader->skip(length);
235             // skip handles padding the read out to a multiple of 4
236         } break;
237         case DRAW_DRRECT: {
238             const SkPaint& paint = *fPictureData->getPaint(reader);
239             SkRRect outer, inner;
240             reader->readRRect(&outer);
241             reader->readRRect(&inner);
242             canvas->drawDRRect(outer, inner, paint);
243         } break;
244         case BEGIN_COMMENT_GROUP:
245             reader->readString();
246             // deprecated (M44)
247             break;
248         case COMMENT:
249             reader->readString();
250             reader->readString();
251             // deprecated (M44)
252             break;
253         case END_COMMENT_GROUP:
254             // deprecated (M44)
255             break;
256         case DRAW_IMAGE: {
257             const SkPaint* paint = fPictureData->getPaint(reader);
258             const SkImage* image = fPictureData->getImage(reader);
259             const SkPoint& loc = reader->skipT<SkPoint>();
260             canvas->drawImage(image, loc.fX, loc.fY, paint);
261         } break;
262         case DRAW_IMAGE_NINE: {
263             const SkPaint* paint = fPictureData->getPaint(reader);
264             const SkImage* image = fPictureData->getImage(reader);
265             const SkIRect& center = reader->skipT<SkIRect>();
266             const SkRect& dst = reader->skipT<SkRect>();
267             canvas->drawImageNine(image, center, dst, paint);
268         } break;
269         case DRAW_IMAGE_RECT_STRICT:
270         case DRAW_IMAGE_RECT: {
271             const SkPaint* paint = fPictureData->getPaint(reader);
272             const SkImage* image = fPictureData->getImage(reader);
273             const SkRect* src = get_rect_ptr(reader);   // may be null
274             const SkRect& dst = reader->skipT<SkRect>();     // required
275             // DRAW_IMAGE_RECT_STRICT assumes this constraint, and doesn't store it
276             SkCanvas::SrcRectConstraint constraint = SkCanvas::kStrict_SrcRectConstraint;
277             if (DRAW_IMAGE_RECT == op) {
278                 // newer op-code stores the constraint explicitly
279                 constraint = (SkCanvas::SrcRectConstraint)reader->readInt();
280             }
281             canvas->legacy_drawImageRect(image, src, dst, paint, constraint);
282         } break;
283         case DRAW_OVAL: {
284             const SkPaint& paint = *fPictureData->getPaint(reader);
285             canvas->drawOval(reader->skipT<SkRect>(), paint);
286         } break;
287         case DRAW_PAINT:
288             canvas->drawPaint(*fPictureData->getPaint(reader));
289             break;
290         case DRAW_PATCH: {
291             const SkPaint& paint = *fPictureData->getPaint(reader);
292 
293             const SkPoint* cubics = (const SkPoint*)reader->skip(SkPatchUtils::kNumCtrlPts *
294                                                                  sizeof(SkPoint));
295             uint32_t flag = reader->readInt();
296             const SkColor* colors = nullptr;
297             if (flag & DRAW_VERTICES_HAS_COLORS) {
298                 colors = (const SkColor*)reader->skip(SkPatchUtils::kNumCorners * sizeof(SkColor));
299             }
300             const SkPoint* texCoords = nullptr;
301             if (flag & DRAW_VERTICES_HAS_TEXS) {
302                 texCoords = (const SkPoint*)reader->skip(SkPatchUtils::kNumCorners *
303                                                          sizeof(SkPoint));
304             }
305             SkAutoTUnref<SkXfermode> xfer;
306             if (flag & DRAW_VERTICES_HAS_XFER) {
307                 int mode = reader->readInt();
308                 if (mode < 0 || mode > SkXfermode::kLastMode) {
309                     mode = SkXfermode::kModulate_Mode;
310                 }
311                 xfer.reset(SkXfermode::Create((SkXfermode::Mode)mode));
312             }
313             canvas->drawPatch(cubics, colors, texCoords, xfer, paint);
314         } break;
315         case DRAW_PATH: {
316             const SkPaint& paint = *fPictureData->getPaint(reader);
317             canvas->drawPath(fPictureData->getPath(reader), paint);
318         } break;
319         case DRAW_PICTURE:
320             canvas->drawPicture(fPictureData->getPicture(reader));
321             break;
322         case DRAW_PICTURE_MATRIX_PAINT: {
323             const SkPaint* paint = fPictureData->getPaint(reader);
324             SkMatrix matrix;
325             reader->readMatrix(&matrix);
326             const SkPicture* pic = fPictureData->getPicture(reader);
327             canvas->drawPicture(pic, &matrix, paint);
328         } break;
329         case DRAW_POINTS: {
330             const SkPaint& paint = *fPictureData->getPaint(reader);
331             SkCanvas::PointMode mode = (SkCanvas::PointMode)reader->readInt();
332             size_t count = reader->readInt();
333             const SkPoint* pts = (const SkPoint*)reader->skip(sizeof(SkPoint)* count);
334             canvas->drawPoints(mode, count, pts, paint);
335         } break;
336         case DRAW_POS_TEXT: {
337             const SkPaint& paint = *fPictureData->getPaint(reader);
338             TextContainer text;
339             get_text(reader, &text);
340             size_t points = reader->readInt();
341             const SkPoint* pos = (const SkPoint*)reader->skip(points * sizeof(SkPoint));
342             canvas->drawPosText(text.text(), text.length(), pos, paint);
343         } break;
344         case DRAW_POS_TEXT_TOP_BOTTOM: {
345             const SkPaint& paint = *fPictureData->getPaint(reader);
346             TextContainer text;
347             get_text(reader, &text);
348             size_t points = reader->readInt();
349             const SkPoint* pos = (const SkPoint*)reader->skip(points * sizeof(SkPoint));
350             const SkScalar top = reader->readScalar();
351             const SkScalar bottom = reader->readScalar();
352             if (!canvas->quickRejectY(top, bottom)) {
353                 canvas->drawPosText(text.text(), text.length(), pos, paint);
354             }
355         } break;
356         case DRAW_POS_TEXT_H: {
357             const SkPaint& paint = *fPictureData->getPaint(reader);
358             TextContainer text;
359             get_text(reader, &text);
360             size_t xCount = reader->readInt();
361             const SkScalar constY = reader->readScalar();
362             const SkScalar* xpos = (const SkScalar*)reader->skip(xCount * sizeof(SkScalar));
363             canvas->drawPosTextH(text.text(), text.length(), xpos, constY, paint);
364         } break;
365         case DRAW_POS_TEXT_H_TOP_BOTTOM: {
366             const SkPaint& paint = *fPictureData->getPaint(reader);
367             TextContainer text;
368             get_text(reader, &text);
369             size_t xCount = reader->readInt();
370             const SkScalar* xpos = (const SkScalar*)reader->skip((3 + xCount) * sizeof(SkScalar));
371             const SkScalar top = *xpos++;
372             const SkScalar bottom = *xpos++;
373             const SkScalar constY = *xpos++;
374             if (!canvas->quickRejectY(top, bottom)) {
375                 canvas->drawPosTextH(text.text(), text.length(), xpos, constY, paint);
376             }
377         } break;
378         case DRAW_RECT: {
379             const SkPaint& paint = *fPictureData->getPaint(reader);
380             canvas->drawRect(reader->skipT<SkRect>(), paint);
381         } break;
382         case DRAW_RRECT: {
383             const SkPaint& paint = *fPictureData->getPaint(reader);
384             SkRRect rrect;
385             reader->readRRect(&rrect);
386             canvas->drawRRect(rrect, paint);
387         } break;
388         case DRAW_SPRITE: {
389             /* const SkPaint* paint = */ fPictureData->getPaint(reader);
390             /* const SkBitmap bitmap = */ shallow_copy(fPictureData->getBitmap(reader));
391             /* int left = */ reader->readInt();
392             /* int top = */ reader->readInt();
393             // drawSprite removed dec-2015
394         } break;
395         case DRAW_TEXT: {
396             const SkPaint& paint = *fPictureData->getPaint(reader);
397             TextContainer text;
398             get_text(reader, &text);
399             SkScalar x = reader->readScalar();
400             SkScalar y = reader->readScalar();
401             canvas->drawText(text.text(), text.length(), x, y, paint);
402         } break;
403         case DRAW_TEXT_BLOB: {
404             const SkPaint& paint = *fPictureData->getPaint(reader);
405             const SkTextBlob* blob = fPictureData->getTextBlob(reader);
406             SkScalar x = reader->readScalar();
407             SkScalar y = reader->readScalar();
408             canvas->drawTextBlob(blob, x, y, paint);
409         } break;
410         case DRAW_TEXT_TOP_BOTTOM: {
411             const SkPaint& paint = *fPictureData->getPaint(reader);
412             TextContainer text;
413             get_text(reader, &text);
414             const SkScalar* ptr = (const SkScalar*)reader->skip(4 * sizeof(SkScalar));
415             // ptr[0] == x
416             // ptr[1] == y
417             // ptr[2] == top
418             // ptr[3] == bottom
419             if (!canvas->quickRejectY(ptr[2], ptr[3])) {
420                 canvas->drawText(text.text(), text.length(), ptr[0], ptr[1], paint);
421             }
422         } break;
423         case DRAW_TEXT_ON_PATH: {
424             const SkPaint& paint = *fPictureData->getPaint(reader);
425             TextContainer text;
426             get_text(reader, &text);
427             const SkPath& path = fPictureData->getPath(reader);
428             SkMatrix matrix;
429             reader->readMatrix(&matrix);
430             canvas->drawTextOnPath(text.text(), text.length(), path, &matrix, paint);
431         } break;
432         case DRAW_VERTICES: {
433             SkAutoTUnref<SkXfermode> xfer;
434             const SkPaint& paint = *fPictureData->getPaint(reader);
435             DrawVertexFlags flags = (DrawVertexFlags)reader->readInt();
436             SkCanvas::VertexMode vmode = (SkCanvas::VertexMode)reader->readInt();
437             int vCount = reader->readInt();
438             const SkPoint* verts = (const SkPoint*)reader->skip(vCount * sizeof(SkPoint));
439             const SkPoint* texs = nullptr;
440             const SkColor* colors = nullptr;
441             const uint16_t* indices = nullptr;
442             int iCount = 0;
443             if (flags & DRAW_VERTICES_HAS_TEXS) {
444                 texs = (const SkPoint*)reader->skip(vCount * sizeof(SkPoint));
445             }
446             if (flags & DRAW_VERTICES_HAS_COLORS) {
447                 colors = (const SkColor*)reader->skip(vCount * sizeof(SkColor));
448             }
449             if (flags & DRAW_VERTICES_HAS_INDICES) {
450                 iCount = reader->readInt();
451                 indices = (const uint16_t*)reader->skip(iCount * sizeof(uint16_t));
452             }
453             if (flags & DRAW_VERTICES_HAS_XFER) {
454                 int mode = reader->readInt();
455                 if (mode < 0 || mode > SkXfermode::kLastMode) {
456                     mode = SkXfermode::kModulate_Mode;
457                 }
458                 xfer.reset(SkXfermode::Create((SkXfermode::Mode)mode));
459             }
460             canvas->drawVertices(vmode, vCount, verts, texs, colors, xfer, indices, iCount, paint);
461         } break;
462         case RESTORE:
463             canvas->restore();
464             break;
465         case ROTATE:
466             canvas->rotate(reader->readScalar());
467             break;
468         case SAVE:
469             // SKPs with version < 29 also store a SaveFlags param.
470             if (size > 4) {
471                 SkASSERT(8 == size);
472                 reader->readInt();
473             }
474             canvas->save();
475             break;
476         case SAVE_LAYER_SAVEFLAGS_DEPRECATED: {
477             const SkRect* boundsPtr = get_rect_ptr(reader);
478             const SkPaint* paint = fPictureData->getPaint(reader);
479             auto flags = SkCanvas::LegacySaveFlagsToSaveLayerFlags(reader->readInt());
480             canvas->saveLayer(SkCanvas::SaveLayerRec(boundsPtr, paint, flags));
481         } break;
482         case SAVE_LAYER_SAVELAYERFLAGS_DEPRECATED_JAN_2016: {
483             const SkRect* boundsPtr = get_rect_ptr(reader);
484             const SkPaint* paint = fPictureData->getPaint(reader);
485             canvas->saveLayer(SkCanvas::SaveLayerRec(boundsPtr, paint, reader->readInt()));
486         } break;
487         case SAVE_LAYER_SAVELAYERREC: {
488             SkCanvas::SaveLayerRec rec(nullptr, nullptr, nullptr, 0);
489             const uint32_t flatFlags = reader->readInt();
490             if (flatFlags & SAVELAYERREC_HAS_BOUNDS) {
491                 rec.fBounds = &reader->skipT<SkRect>();
492             }
493             if (flatFlags & SAVELAYERREC_HAS_PAINT) {
494                 rec.fPaint = fPictureData->getPaint(reader);
495             }
496             if (flatFlags & SAVELAYERREC_HAS_BACKDROP) {
497                 const SkPaint* paint = fPictureData->getPaint(reader);
498                 rec.fBackdrop = paint->getImageFilter();
499             }
500             if (flatFlags & SAVELAYERREC_HAS_FLAGS) {
501                 rec.fSaveLayerFlags = reader->readInt();
502             }
503             canvas->saveLayer(rec);
504         } break;
505         case SCALE: {
506             SkScalar sx = reader->readScalar();
507             SkScalar sy = reader->readScalar();
508             canvas->scale(sx, sy);
509         } break;
510         case SET_MATRIX: {
511             SkMatrix matrix;
512             reader->readMatrix(&matrix);
513             matrix.postConcat(initialMatrix);
514             canvas->setMatrix(matrix);
515         } break;
516         case SKEW: {
517             SkScalar sx = reader->readScalar();
518             SkScalar sy = reader->readScalar();
519             canvas->skew(sx, sy);
520         } break;
521         case TRANSLATE: {
522             SkScalar dx = reader->readScalar();
523             SkScalar dy = reader->readScalar();
524             canvas->translate(dx, dy);
525         } break;
526         default:
527             SkASSERTF(false, "Unknown draw type: %d", op);
528     }
529 }
530 
531