2 * Copyright 2014 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
9 #include "SkPatchUtils.h"
10 #include "SkPictureData.h"
11 #include "SkPicturePlayback.h"
12 #include "SkPictureRecord.h"
13 #include "SkPictureStateTree.h"
14 #include "SkReader32.h"
15 #include "SkTextBlob.h"
16 #include "SkTDArray.h"
20 * Read the next op code and chunk size from 'reader'. The returned size
21 * is the entire size of the chunk (including the opcode). Thus, the
22 * offset just prior to calling ReadOpAndSize + 'size' is the offset
23 * to the next chunk's op code. This also means that the size of a chunk
24 * with no arguments (just an opcode) will be 4.
26 DrawType SkPicturePlayback::ReadOpAndSize(SkReader32* reader, uint32_t* size) {
27 uint32_t temp = reader->readInt();
29 if (((uint8_t)temp) == temp) {
30 // old skp file - no size information
34 UNPACK_8_24(temp, op, *size);
35 if (MASK_24 == *size) {
36 *size = reader->readInt();
43 static const SkRect* get_rect_ptr(SkReader32* reader) {
44 if (reader->readBool()) {
45 return &reader->skipT<SkRect>();
53 size_t length() { return fByteLength; }
54 const void* text() { return (const void*)fText; }
59 void get_text(SkReader32* reader, TextContainer* text) {
60 size_t length = text->fByteLength = reader->readInt();
61 text->fText = (const char*)reader->skip(length);
64 // FIXME: SkBitmaps are stateful, so we need to copy them to play back in multiple threads.
65 static SkBitmap shallow_copy(const SkBitmap& bitmap) {
69 const SkPicture::OperationList* SkPicturePlayback::getActiveOps(const SkCanvas* canvas) {
73 if (canvas->getClipBounds(&clipBounds)) {
74 return fPictureData->getActiveOps(clipBounds);
81 // Initialize the state tree iterator. Return false if there is nothing left to draw.
82 bool SkPicturePlayback::initIterator(SkPictureStateTree::Iterator* iter,
84 const SkPicture::OperationList *activeOpsList) {
87 if (0 == activeOpsList->numOps()) {
88 return false; // nothing to draw
91 fPictureData->initIterator(iter, activeOpsList->fOps, canvas);
97 // If 'iter' is valid use it to skip forward through the picture.
98 void SkPicturePlayback::StepIterator(SkPictureStateTree::Iterator* iter, SkReader32* reader) {
99 if (iter->isValid()) {
100 uint32_t skipTo = iter->nextDraw();
101 if (SkPictureStateTree::Iterator::kDrawComplete == skipTo) {
102 reader->setOffset(reader->size()); // skip to end
104 reader->setOffset(skipTo);
109 // Update the iterator and state tree to catch up with the skipped ops.
110 void SkPicturePlayback::SkipIterTo(SkPictureStateTree::Iterator* iter,
113 SkASSERT(skipTo <= reader->size());
114 SkASSERT(reader->offset() <= skipTo); // should only be skipping forward
116 if (iter->isValid()) {
117 // If using a bounding box hierarchy, advance the state tree
118 // iterator until at or after skipTo
119 uint32_t adjustedSkipTo;
121 adjustedSkipTo = iter->nextDraw();
122 } while (adjustedSkipTo < skipTo);
123 skipTo = adjustedSkipTo;
125 if (SkPictureStateTree::Iterator::kDrawComplete == skipTo) {
126 reader->setOffset(reader->size()); // skip to end
128 reader->setOffset(skipTo);
132 void SkPicturePlayback::draw(SkCanvas* canvas, SkDrawPictureCallback* callback) {
133 AutoResetOpID aroi(this);
134 SkASSERT(0 == fCurOffset);
136 SkAutoTDelete<const SkPicture::OperationList> activeOpsList(this->getActiveOps(canvas));
137 SkPictureStateTree::Iterator it;
139 if (!this->initIterator(&it, canvas, activeOpsList.get())) {
140 return; // nothing to draw
143 SkReader32 reader(fPictureData->opData()->bytes(), fPictureData->opData()->size());
145 StepIterator(&it, &reader);
147 // Record this, so we can concat w/ it if we encounter a setMatrix()
148 SkMatrix initialMatrix = canvas->getTotalMatrix();
150 SkAutoCanvasRestore acr(canvas, false);
152 while (!reader.eof()) {
153 if (callback && callback->abortDrawing()) {
157 fCurOffset = reader.offset();
159 DrawType op = ReadOpAndSize(&reader, &size);
161 // NOOPs are to be ignored - do not propagate them any further
162 SkipIterTo(&it, &reader, fCurOffset + size);
166 this->handleOp(&reader, op, size, canvas, initialMatrix);
168 StepIterator(&it, &reader);
172 void SkPicturePlayback::handleOp(SkReader32* reader,
176 const SkMatrix& initialMatrix) {
179 const SkPath& path = fPictureData->getPath(reader);
180 uint32_t packed = reader->readInt();
181 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
182 bool doAA = ClipParams_unpackDoAA(packed);
183 size_t offsetToRestore = reader->readInt();
184 SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
185 canvas->clipPath(path, regionOp, doAA);
186 if (canvas->isClipEmpty() && offsetToRestore) {
187 reader->setOffset(offsetToRestore);
192 reader->readRegion(®ion);
193 uint32_t packed = reader->readInt();
194 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
195 size_t offsetToRestore = reader->readInt();
196 SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
197 canvas->clipRegion(region, regionOp);
198 if (canvas->isClipEmpty() && offsetToRestore) {
199 reader->setOffset(offsetToRestore);
203 const SkRect& rect = reader->skipT<SkRect>();
204 uint32_t packed = reader->readInt();
205 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
206 bool doAA = ClipParams_unpackDoAA(packed);
207 size_t offsetToRestore = reader->readInt();
208 SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
209 canvas->clipRect(rect, regionOp, doAA);
210 if (canvas->isClipEmpty() && offsetToRestore) {
211 reader->setOffset(offsetToRestore);
216 reader->readRRect(&rrect);
217 uint32_t packed = reader->readInt();
218 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
219 bool doAA = ClipParams_unpackDoAA(packed);
220 size_t offsetToRestore = reader->readInt();
221 SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
222 canvas->clipRRect(rrect, regionOp, doAA);
223 if (canvas->isClipEmpty() && offsetToRestore) {
224 reader->setOffset(offsetToRestore);
228 const SkRect& cullRect = reader->skipT<SkRect>();
229 size_t offsetToRestore = reader->readInt();
230 if (offsetToRestore && canvas->quickReject(cullRect)) {
231 reader->setOffset(offsetToRestore);
233 canvas->pushCull(cullRect);
241 reader->readMatrix(&matrix);
242 canvas->concat(matrix);
246 const SkPaint* paint = fPictureData->getPaint(reader);
247 const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
248 const SkPoint& loc = reader->skipT<SkPoint>();
249 canvas->drawBitmap(bitmap, loc.fX, loc.fY, paint);
251 case DRAW_BITMAP_RECT_TO_RECT: {
252 const SkPaint* paint = fPictureData->getPaint(reader);
253 const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
254 const SkRect* src = get_rect_ptr(reader); // may be null
255 const SkRect& dst = reader->skipT<SkRect>(); // required
256 SkCanvas::DrawBitmapRectFlags flags;
257 flags = (SkCanvas::DrawBitmapRectFlags) reader->readInt();
258 canvas->drawBitmapRectToRect(bitmap, src, dst, paint, flags);
260 case DRAW_BITMAP_MATRIX: {
261 const SkPaint* paint = fPictureData->getPaint(reader);
262 const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
264 reader->readMatrix(&matrix);
265 canvas->drawBitmapMatrix(bitmap, matrix, paint);
267 case DRAW_BITMAP_NINE: {
268 const SkPaint* paint = fPictureData->getPaint(reader);
269 const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
270 const SkIRect& src = reader->skipT<SkIRect>();
271 const SkRect& dst = reader->skipT<SkRect>();
272 canvas->drawBitmapNine(bitmap, src, dst, paint);
275 canvas->clear(reader->readInt());
278 size_t length = reader->readInt();
279 canvas->drawData(reader->skip(length), length);
280 // skip handles padding the read out to a multiple of 4
283 const SkPaint& paint = *fPictureData->getPaint(reader);
284 SkRRect outer, inner;
285 reader->readRRect(&outer);
286 reader->readRRect(&inner);
287 canvas->drawDRRect(outer, inner, paint);
289 case BEGIN_COMMENT_GROUP: {
290 const char* desc = reader->readString();
291 canvas->beginCommentGroup(desc);
294 const char* kywd = reader->readString();
295 const char* value = reader->readString();
296 canvas->addComment(kywd, value);
298 case END_COMMENT_GROUP: {
299 canvas->endCommentGroup();
302 const SkPaint& paint = *fPictureData->getPaint(reader);
303 canvas->drawOval(reader->skipT<SkRect>(), paint);
306 canvas->drawPaint(*fPictureData->getPaint(reader));
309 const SkPaint& paint = *fPictureData->getPaint(reader);
311 const SkPoint* cubics = (const SkPoint*)reader->skip(SkPatchUtils::kNumCtrlPts *
313 uint32_t flag = reader->readInt();
314 const SkColor* colors = NULL;
315 if (flag & DRAW_VERTICES_HAS_COLORS) {
316 colors = (const SkColor*)reader->skip(SkPatchUtils::kNumCorners * sizeof(SkColor));
318 const SkPoint* texCoords = NULL;
319 if (flag & DRAW_VERTICES_HAS_TEXS) {
320 texCoords = (const SkPoint*)reader->skip(SkPatchUtils::kNumCorners *
323 SkAutoTUnref<SkXfermode> xfer;
324 if (flag & DRAW_VERTICES_HAS_XFER) {
325 int mode = reader->readInt();
326 if (mode < 0 || mode > SkXfermode::kLastMode) {
327 mode = SkXfermode::kModulate_Mode;
329 xfer.reset(SkXfermode::Create((SkXfermode::Mode)mode));
331 canvas->drawPatch(cubics, colors, texCoords, xfer, paint);
334 const SkPaint& paint = *fPictureData->getPaint(reader);
335 canvas->drawPath(fPictureData->getPath(reader), paint);
338 canvas->drawPicture(fPictureData->getPicture(reader));
340 case DRAW_PICTURE_MATRIX_PAINT: {
341 const SkPaint* paint = fPictureData->getPaint(reader);
343 reader->readMatrix(&matrix);
344 const SkPicture* pic = fPictureData->getPicture(reader);
345 canvas->drawPicture(pic, &matrix, paint);
348 const SkPaint& paint = *fPictureData->getPaint(reader);
349 SkCanvas::PointMode mode = (SkCanvas::PointMode)reader->readInt();
350 size_t count = reader->readInt();
351 const SkPoint* pts = (const SkPoint*)reader->skip(sizeof(SkPoint)* count);
352 canvas->drawPoints(mode, count, pts, paint);
354 case DRAW_POS_TEXT: {
355 const SkPaint& paint = *fPictureData->getPaint(reader);
357 get_text(reader, &text);
358 size_t points = reader->readInt();
359 const SkPoint* pos = (const SkPoint*)reader->skip(points * sizeof(SkPoint));
360 canvas->drawPosText(text.text(), text.length(), pos, paint);
362 case DRAW_POS_TEXT_TOP_BOTTOM: {
363 const SkPaint& paint = *fPictureData->getPaint(reader);
365 get_text(reader, &text);
366 size_t points = reader->readInt();
367 const SkPoint* pos = (const SkPoint*)reader->skip(points * sizeof(SkPoint));
368 const SkScalar top = reader->readScalar();
369 const SkScalar bottom = reader->readScalar();
370 if (!canvas->quickRejectY(top, bottom)) {
371 canvas->drawPosText(text.text(), text.length(), pos, paint);
374 case DRAW_POS_TEXT_H: {
375 const SkPaint& paint = *fPictureData->getPaint(reader);
377 get_text(reader, &text);
378 size_t xCount = reader->readInt();
379 const SkScalar constY = reader->readScalar();
380 const SkScalar* xpos = (const SkScalar*)reader->skip(xCount * sizeof(SkScalar));
381 canvas->drawPosTextH(text.text(), text.length(), xpos, constY, paint);
383 case DRAW_POS_TEXT_H_TOP_BOTTOM: {
384 const SkPaint& paint = *fPictureData->getPaint(reader);
386 get_text(reader, &text);
387 size_t xCount = reader->readInt();
388 const SkScalar* xpos = (const SkScalar*)reader->skip((3 + xCount) * sizeof(SkScalar));
389 const SkScalar top = *xpos++;
390 const SkScalar bottom = *xpos++;
391 const SkScalar constY = *xpos++;
392 if (!canvas->quickRejectY(top, bottom)) {
393 canvas->drawPosTextH(text.text(), text.length(), xpos, constY, paint);
397 const SkPaint& paint = *fPictureData->getPaint(reader);
398 canvas->drawRect(reader->skipT<SkRect>(), paint);
401 const SkPaint& paint = *fPictureData->getPaint(reader);
403 reader->readRRect(&rrect);
404 canvas->drawRRect(rrect, paint);
407 const SkPaint* paint = fPictureData->getPaint(reader);
408 const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
409 int left = reader->readInt();
410 int top = reader->readInt();
411 canvas->drawSprite(bitmap, left, top, paint);
414 const SkPaint& paint = *fPictureData->getPaint(reader);
416 get_text(reader, &text);
417 SkScalar x = reader->readScalar();
418 SkScalar y = reader->readScalar();
419 canvas->drawText(text.text(), text.length(), x, y, paint);
421 case DRAW_TEXT_BLOB: {
422 const SkPaint& paint = *fPictureData->getPaint(reader);
423 const SkTextBlob* blob = fPictureData->getTextBlob(reader);
424 SkScalar x = reader->readScalar();
425 SkScalar y = reader->readScalar();
426 canvas->drawTextBlob(blob, x, y, paint);
428 case DRAW_TEXT_TOP_BOTTOM: {
429 const SkPaint& paint = *fPictureData->getPaint(reader);
431 get_text(reader, &text);
432 const SkScalar* ptr = (const SkScalar*)reader->skip(4 * sizeof(SkScalar));
437 if (!canvas->quickRejectY(ptr[2], ptr[3])) {
438 canvas->drawText(text.text(), text.length(), ptr[0], ptr[1], paint);
441 case DRAW_TEXT_ON_PATH: {
442 const SkPaint& paint = *fPictureData->getPaint(reader);
444 get_text(reader, &text);
445 const SkPath& path = fPictureData->getPath(reader);
447 reader->readMatrix(&matrix);
448 canvas->drawTextOnPath(text.text(), text.length(), path, &matrix, paint);
450 case DRAW_VERTICES: {
451 SkAutoTUnref<SkXfermode> xfer;
452 const SkPaint& paint = *fPictureData->getPaint(reader);
453 DrawVertexFlags flags = (DrawVertexFlags)reader->readInt();
454 SkCanvas::VertexMode vmode = (SkCanvas::VertexMode)reader->readInt();
455 int vCount = reader->readInt();
456 const SkPoint* verts = (const SkPoint*)reader->skip(vCount * sizeof(SkPoint));
457 const SkPoint* texs = NULL;
458 const SkColor* colors = NULL;
459 const uint16_t* indices = NULL;
461 if (flags & DRAW_VERTICES_HAS_TEXS) {
462 texs = (const SkPoint*)reader->skip(vCount * sizeof(SkPoint));
464 if (flags & DRAW_VERTICES_HAS_COLORS) {
465 colors = (const SkColor*)reader->skip(vCount * sizeof(SkColor));
467 if (flags & DRAW_VERTICES_HAS_INDICES) {
468 iCount = reader->readInt();
469 indices = (const uint16_t*)reader->skip(iCount * sizeof(uint16_t));
471 if (flags & DRAW_VERTICES_HAS_XFER) {
472 int mode = reader->readInt();
473 if (mode < 0 || mode > SkXfermode::kLastMode) {
474 mode = SkXfermode::kModulate_Mode;
476 xfer.reset(SkXfermode::Create((SkXfermode::Mode)mode));
478 canvas->drawVertices(vmode, vCount, verts, texs, colors, xfer, indices, iCount, paint);
484 canvas->rotate(reader->readScalar());
487 // SKPs with version < 29 also store a SaveFlags param.
495 const SkRect* boundsPtr = get_rect_ptr(reader);
496 const SkPaint* paint = fPictureData->getPaint(reader);
497 canvas->saveLayer(boundsPtr, paint, (SkCanvas::SaveFlags) reader->readInt());
500 SkScalar sx = reader->readScalar();
501 SkScalar sy = reader->readScalar();
502 canvas->scale(sx, sy);
506 reader->readMatrix(&matrix);
507 matrix.postConcat(initialMatrix);
508 canvas->setMatrix(matrix);
511 SkScalar sx = reader->readScalar();
512 SkScalar sy = reader->readScalar();
513 canvas->skew(sx, sy);
516 SkScalar dx = reader->readScalar();
517 SkScalar dy = reader->readScalar();
518 canvas->translate(dx, dy);