SkPicturePlayback.cpp revision c26d991bf2d85bb1843a21b0a4f861212b0eaced
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 "SkPictureData.h" 10#include "SkPicturePlayback.h" 11#include "SkPictureRecord.h" 12#include "SkPictureStateTree.h" 13#include "SkReader32.h" 14#include "SkTDArray.h" 15#include "SkTypes.h" 16 17/* 18 * Read the next op code and chunk size from 'reader'. The returned size 19 * is the entire size of the chunk (including the opcode). Thus, the 20 * offset just prior to calling ReadOpAndSize + 'size' is the offset 21 * to the next chunk's op code. This also means that the size of a chunk 22 * with no arguments (just an opcode) will be 4. 23 */ 24DrawType SkPicturePlayback::ReadOpAndSize(SkReader32* reader, uint32_t* size) { 25 uint32_t temp = reader->readInt(); 26 uint32_t op; 27 if (((uint8_t)temp) == temp) { 28 // old skp file - no size information 29 op = temp; 30 *size = 0; 31 } else { 32 UNPACK_8_24(temp, op, *size); 33 if (MASK_24 == *size) { 34 *size = reader->readInt(); 35 } 36 } 37 return (DrawType)op; 38} 39 40 41static const SkRect* get_rect_ptr(SkReader32* reader) { 42 if (reader->readBool()) { 43 return &reader->skipT<SkRect>(); 44 } else { 45 return NULL; 46 } 47} 48 49class TextContainer { 50public: 51 size_t length() { return fByteLength; } 52 const void* text() { return (const void*)fText; } 53 size_t fByteLength; 54 const char* fText; 55}; 56 57void get_text(SkReader32* reader, TextContainer* text) { 58 size_t length = text->fByteLength = reader->readInt(); 59 text->fText = (const char*)reader->skip(length); 60} 61 62// FIXME: SkBitmaps are stateful, so we need to copy them to play back in multiple threads. 63static SkBitmap shallow_copy(const SkBitmap& bitmap) { 64 return bitmap; 65} 66 67const SkPicture::OperationList* SkPicturePlayback::getActiveOps(const SkCanvas* canvas) { 68 69 if (fUseBBH && NULL != fPictureData->fStateTree && NULL != fPictureData->fBoundingHierarchy) { 70 SkRect clipBounds; 71 if (canvas->getClipBounds(&clipBounds)) { 72 SkIRect query; 73 clipBounds.roundOut(&query); 74 75 return fPictureData->getActiveOps(query); 76 } 77 } 78 79 return NULL; 80} 81 82// Initialize the state tree iterator. Return false if there is nothing left to draw. 83bool SkPicturePlayback::initIterator(SkPictureStateTree::Iterator* iter, 84 SkCanvas* canvas, 85 const SkPicture::OperationList *activeOpsList) { 86 87 if (NULL != activeOpsList) { 88 if (0 == activeOpsList->numOps()) { 89 return false; // nothing to draw 90 } 91 92 fPictureData->fStateTree->initIterator(iter, activeOpsList->fOps, canvas); 93 } 94 95 return true; 96} 97 98// If 'iter' is valid use it to skip forward through the picture. 99void SkPicturePlayback::StepIterator(SkPictureStateTree::Iterator* iter, SkReader32* reader) { 100 if (iter->isValid()) { 101 uint32_t skipTo = iter->nextDraw(); 102 if (SkPictureStateTree::Iterator::kDrawComplete == skipTo) { 103 reader->setOffset(reader->size()); // skip to end 104 } else { 105 reader->setOffset(skipTo); 106 } 107 } 108} 109 110// Update the iterator and state tree to catch up with the skipped ops. 111void SkPicturePlayback::SkipIterTo(SkPictureStateTree::Iterator* iter, 112 SkReader32* reader, 113 uint32_t skipTo) { 114 SkASSERT(skipTo <= reader->size()); 115 SkASSERT(reader->offset() <= skipTo); // should only be skipping forward 116 117 if (iter->isValid()) { 118 // If using a bounding box hierarchy, advance the state tree 119 // iterator until at or after skipTo 120 uint32_t adjustedSkipTo; 121 do { 122 adjustedSkipTo = iter->nextDraw(); 123 } while (adjustedSkipTo < skipTo); 124 skipTo = adjustedSkipTo; 125 } 126 if (SkPictureStateTree::Iterator::kDrawComplete == skipTo) { 127 reader->setOffset(reader->size()); // skip to end 128 } else { 129 reader->setOffset(skipTo); 130 } 131} 132 133void SkPicturePlayback::draw(SkCanvas* canvas, SkDrawPictureCallback* callback) { 134 AutoResetOpID aroi(this); 135 SkASSERT(0 == fCurOffset); 136 137 SkAutoTDelete<const SkPicture::OperationList> activeOpsList(this->getActiveOps(canvas)); 138 SkPictureStateTree::Iterator it; 139 140 if (!this->initIterator(&it, canvas, activeOpsList.get())) { 141 return; // nothing to draw 142 } 143 144 SkReader32 reader(fPictureData->opData()->bytes(), fPictureData->opData()->size()); 145 146 StepIterator(&it, &reader); 147 148 // Record this, so we can concat w/ it if we encounter a setMatrix() 149 SkMatrix initialMatrix = canvas->getTotalMatrix(); 150 151 SkAutoCanvasRestore acr(canvas, false); 152 153 while (!reader.eof()) { 154 if (NULL != callback && callback->abortDrawing()) { 155 return; 156 } 157 158 fCurOffset = reader.offset(); 159 uint32_t size; 160 DrawType op = ReadOpAndSize(&reader, &size); 161 if (NOOP == op) { 162 // NOOPs are to be ignored - do not propagate them any further 163 SkipIterTo(&it, &reader, fCurOffset + size); 164 continue; 165 } 166 167 this->handleOp(&reader, op, size, canvas, initialMatrix); 168 169 StepIterator(&it, &reader); 170 } 171} 172 173void SkPicturePlayback::handleOp(SkReader32* reader, 174 DrawType op, 175 uint32_t size, 176 SkCanvas* canvas, 177 const SkMatrix& initialMatrix) { 178 switch (op) { 179 case CLIP_PATH: { 180 const SkPath& path = fPictureData->getPath(reader); 181 uint32_t packed = reader->readInt(); 182 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed); 183 bool doAA = ClipParams_unpackDoAA(packed); 184 size_t offsetToRestore = reader->readInt(); 185 SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset()); 186 canvas->clipPath(path, regionOp, doAA); 187 if (canvas->isClipEmpty() && offsetToRestore) { 188 reader->setOffset(offsetToRestore); 189 } 190 } break; 191 case CLIP_REGION: { 192 SkRegion region; 193 reader->readRegion(®ion); 194 uint32_t packed = reader->readInt(); 195 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed); 196 size_t offsetToRestore = reader->readInt(); 197 SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset()); 198 canvas->clipRegion(region, regionOp); 199 if (canvas->isClipEmpty() && offsetToRestore) { 200 reader->setOffset(offsetToRestore); 201 } 202 } break; 203 case CLIP_RECT: { 204 const SkRect& rect = reader->skipT<SkRect>(); 205 uint32_t packed = reader->readInt(); 206 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed); 207 bool doAA = ClipParams_unpackDoAA(packed); 208 size_t offsetToRestore = reader->readInt(); 209 SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset()); 210 canvas->clipRect(rect, regionOp, doAA); 211 if (canvas->isClipEmpty() && offsetToRestore) { 212 reader->setOffset(offsetToRestore); 213 } 214 } break; 215 case CLIP_RRECT: { 216 SkRRect rrect; 217 reader->readRRect(&rrect); 218 uint32_t packed = reader->readInt(); 219 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed); 220 bool doAA = ClipParams_unpackDoAA(packed); 221 size_t offsetToRestore = reader->readInt(); 222 SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset()); 223 canvas->clipRRect(rrect, regionOp, doAA); 224 if (canvas->isClipEmpty() && offsetToRestore) { 225 reader->setOffset(offsetToRestore); 226 } 227 } break; 228 case PUSH_CULL: { 229 const SkRect& cullRect = reader->skipT<SkRect>(); 230 size_t offsetToRestore = reader->readInt(); 231 if (offsetToRestore && canvas->quickReject(cullRect)) { 232 reader->setOffset(offsetToRestore); 233 } else { 234 canvas->pushCull(cullRect); 235 } 236 } break; 237 case POP_CULL: 238 canvas->popCull(); 239 break; 240 case CONCAT: { 241 SkMatrix matrix; 242 reader->readMatrix(&matrix); 243 canvas->concat(matrix); 244 break; 245 } 246 case DRAW_BITMAP: { 247 const SkPaint* paint = fPictureData->getPaint(reader); 248 const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader)); 249 const SkPoint& loc = reader->skipT<SkPoint>(); 250 canvas->drawBitmap(bitmap, loc.fX, loc.fY, paint); 251 } break; 252 case DRAW_BITMAP_RECT_TO_RECT: { 253 const SkPaint* paint = fPictureData->getPaint(reader); 254 const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader)); 255 const SkRect* src = get_rect_ptr(reader); // may be null 256 const SkRect& dst = reader->skipT<SkRect>(); // required 257 SkCanvas::DrawBitmapRectFlags flags; 258 flags = (SkCanvas::DrawBitmapRectFlags) reader->readInt(); 259 canvas->drawBitmapRectToRect(bitmap, src, dst, paint, flags); 260 } break; 261 case DRAW_BITMAP_MATRIX: { 262 const SkPaint* paint = fPictureData->getPaint(reader); 263 const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader)); 264 SkMatrix matrix; 265 reader->readMatrix(&matrix); 266 canvas->drawBitmapMatrix(bitmap, matrix, paint); 267 } break; 268 case DRAW_BITMAP_NINE: { 269 const SkPaint* paint = fPictureData->getPaint(reader); 270 const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader)); 271 const SkIRect& src = reader->skipT<SkIRect>(); 272 const SkRect& dst = reader->skipT<SkRect>(); 273 canvas->drawBitmapNine(bitmap, src, dst, paint); 274 } break; 275 case DRAW_CLEAR: 276 canvas->clear(reader->readInt()); 277 break; 278 case DRAW_DATA: { 279 size_t length = reader->readInt(); 280 canvas->drawData(reader->skip(length), length); 281 // skip handles padding the read out to a multiple of 4 282 } break; 283 case DRAW_DRRECT: { 284 const SkPaint& paint = *fPictureData->getPaint(reader); 285 SkRRect outer, inner; 286 reader->readRRect(&outer); 287 reader->readRRect(&inner); 288 canvas->drawDRRect(outer, inner, paint); 289 } break; 290 case BEGIN_COMMENT_GROUP: { 291 const char* desc = reader->readString(); 292 canvas->beginCommentGroup(desc); 293 } break; 294 case COMMENT: { 295 const char* kywd = reader->readString(); 296 const char* value = reader->readString(); 297 canvas->addComment(kywd, value); 298 } break; 299 case END_COMMENT_GROUP: { 300 canvas->endCommentGroup(); 301 } break; 302 case DRAW_OVAL: { 303 const SkPaint& paint = *fPictureData->getPaint(reader); 304 canvas->drawOval(reader->skipT<SkRect>(), paint); 305 } break; 306 case DRAW_PAINT: 307 canvas->drawPaint(*fPictureData->getPaint(reader)); 308 break; 309 case DRAW_PATH: { 310 const SkPaint& paint = *fPictureData->getPaint(reader); 311 canvas->drawPath(fPictureData->getPath(reader), paint); 312 } break; 313 case DRAW_PICTURE: 314 canvas->drawPicture(fPictureData->getPicture(reader)); 315 break; 316 case DRAW_POINTS: { 317 const SkPaint& paint = *fPictureData->getPaint(reader); 318 SkCanvas::PointMode mode = (SkCanvas::PointMode)reader->readInt(); 319 size_t count = reader->readInt(); 320 const SkPoint* pts = (const SkPoint*)reader->skip(sizeof(SkPoint)* count); 321 canvas->drawPoints(mode, count, pts, paint); 322 } break; 323 case DRAW_POS_TEXT: { 324 const SkPaint& paint = *fPictureData->getPaint(reader); 325 TextContainer text; 326 get_text(reader, &text); 327 size_t points = reader->readInt(); 328 const SkPoint* pos = (const SkPoint*)reader->skip(points * sizeof(SkPoint)); 329 canvas->drawPosText(text.text(), text.length(), pos, paint); 330 } break; 331 case DRAW_POS_TEXT_TOP_BOTTOM: { 332 const SkPaint& paint = *fPictureData->getPaint(reader); 333 TextContainer text; 334 get_text(reader, &text); 335 size_t points = reader->readInt(); 336 const SkPoint* pos = (const SkPoint*)reader->skip(points * sizeof(SkPoint)); 337 const SkScalar top = reader->readScalar(); 338 const SkScalar bottom = reader->readScalar(); 339 if (!canvas->quickRejectY(top, bottom)) { 340 canvas->drawPosText(text.text(), text.length(), pos, paint); 341 } 342 } break; 343 case DRAW_POS_TEXT_H: { 344 const SkPaint& paint = *fPictureData->getPaint(reader); 345 TextContainer text; 346 get_text(reader, &text); 347 size_t xCount = reader->readInt(); 348 const SkScalar constY = reader->readScalar(); 349 const SkScalar* xpos = (const SkScalar*)reader->skip(xCount * sizeof(SkScalar)); 350 canvas->drawPosTextH(text.text(), text.length(), xpos, constY, paint); 351 } break; 352 case DRAW_POS_TEXT_H_TOP_BOTTOM: { 353 const SkPaint& paint = *fPictureData->getPaint(reader); 354 TextContainer text; 355 get_text(reader, &text); 356 size_t xCount = reader->readInt(); 357 const SkScalar* xpos = (const SkScalar*)reader->skip((3 + xCount) * sizeof(SkScalar)); 358 const SkScalar top = *xpos++; 359 const SkScalar bottom = *xpos++; 360 const SkScalar constY = *xpos++; 361 if (!canvas->quickRejectY(top, bottom)) { 362 canvas->drawPosTextH(text.text(), text.length(), xpos, constY, paint); 363 } 364 } break; 365 case DRAW_RECT: { 366 const SkPaint& paint = *fPictureData->getPaint(reader); 367 canvas->drawRect(reader->skipT<SkRect>(), paint); 368 } break; 369 case DRAW_RRECT: { 370 const SkPaint& paint = *fPictureData->getPaint(reader); 371 SkRRect rrect; 372 reader->readRRect(&rrect); 373 canvas->drawRRect(rrect, paint); 374 } break; 375 case DRAW_SPRITE: { 376 const SkPaint* paint = fPictureData->getPaint(reader); 377 const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader)); 378 int left = reader->readInt(); 379 int top = reader->readInt(); 380 canvas->drawSprite(bitmap, left, top, paint); 381 } break; 382 case DRAW_TEXT: { 383 const SkPaint& paint = *fPictureData->getPaint(reader); 384 TextContainer text; 385 get_text(reader, &text); 386 SkScalar x = reader->readScalar(); 387 SkScalar y = reader->readScalar(); 388 canvas->drawText(text.text(), text.length(), x, y, paint); 389 } break; 390 case DRAW_TEXT_TOP_BOTTOM: { 391 const SkPaint& paint = *fPictureData->getPaint(reader); 392 TextContainer text; 393 get_text(reader, &text); 394 const SkScalar* ptr = (const SkScalar*)reader->skip(4 * sizeof(SkScalar)); 395 // ptr[0] == x 396 // ptr[1] == y 397 // ptr[2] == top 398 // ptr[3] == bottom 399 if (!canvas->quickRejectY(ptr[2], ptr[3])) { 400 canvas->drawText(text.text(), text.length(), ptr[0], ptr[1], paint); 401 } 402 } break; 403 case DRAW_TEXT_ON_PATH: { 404 const SkPaint& paint = *fPictureData->getPaint(reader); 405 TextContainer text; 406 get_text(reader, &text); 407 const SkPath& path = fPictureData->getPath(reader); 408 SkMatrix matrix; 409 reader->readMatrix(&matrix); 410 canvas->drawTextOnPath(text.text(), text.length(), path, &matrix, paint); 411 } break; 412 case DRAW_VERTICES: { 413 SkAutoTUnref<SkXfermode> xfer; 414 const SkPaint& paint = *fPictureData->getPaint(reader); 415 DrawVertexFlags flags = (DrawVertexFlags)reader->readInt(); 416 SkCanvas::VertexMode vmode = (SkCanvas::VertexMode)reader->readInt(); 417 int vCount = reader->readInt(); 418 const SkPoint* verts = (const SkPoint*)reader->skip(vCount * sizeof(SkPoint)); 419 const SkPoint* texs = NULL; 420 const SkColor* colors = NULL; 421 const uint16_t* indices = NULL; 422 int iCount = 0; 423 if (flags & DRAW_VERTICES_HAS_TEXS) { 424 texs = (const SkPoint*)reader->skip(vCount * sizeof(SkPoint)); 425 } 426 if (flags & DRAW_VERTICES_HAS_COLORS) { 427 colors = (const SkColor*)reader->skip(vCount * sizeof(SkColor)); 428 } 429 if (flags & DRAW_VERTICES_HAS_INDICES) { 430 iCount = reader->readInt(); 431 indices = (const uint16_t*)reader->skip(iCount * sizeof(uint16_t)); 432 } 433 if (flags & DRAW_VERTICES_HAS_XFER) { 434 int mode = reader->readInt(); 435 if (mode < 0 || mode > SkXfermode::kLastMode) { 436 mode = SkXfermode::kModulate_Mode; 437 } 438 xfer.reset(SkXfermode::Create((SkXfermode::Mode)mode)); 439 } 440 canvas->drawVertices(vmode, vCount, verts, texs, colors, xfer, indices, iCount, paint); 441 } break; 442 case RESTORE: 443 canvas->restore(); 444 break; 445 case ROTATE: 446 canvas->rotate(reader->readScalar()); 447 break; 448 case SAVE: 449 // SKPs with version < 29 also store a SaveFlags param. 450 if (size > 4) { 451 SkASSERT(8 == size); 452 reader->readInt(); 453 } 454 canvas->save(); 455 break; 456 case SAVE_LAYER: { 457 const SkRect* boundsPtr = get_rect_ptr(reader); 458 const SkPaint* paint = fPictureData->getPaint(reader); 459 canvas->saveLayer(boundsPtr, paint, (SkCanvas::SaveFlags) reader->readInt()); 460 } break; 461 case SCALE: { 462 SkScalar sx = reader->readScalar(); 463 SkScalar sy = reader->readScalar(); 464 canvas->scale(sx, sy); 465 } break; 466 case SET_MATRIX: { 467 SkMatrix matrix; 468 reader->readMatrix(&matrix); 469 matrix.postConcat(initialMatrix); 470 canvas->setMatrix(matrix); 471 } break; 472 case SKEW: { 473 SkScalar sx = reader->readScalar(); 474 SkScalar sy = reader->readScalar(); 475 canvas->skew(sx, sy); 476 } break; 477 case TRANSLATE: { 478 SkScalar dx = reader->readScalar(); 479 SkScalar dy = reader->readScalar(); 480 canvas->translate(dx, dy); 481 } break; 482 default: 483 SkASSERT(0); 484 } 485} 486 487