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(®ion);
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