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 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 */ 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 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: 71 size_t length() { return fByteLength; } 72 const void* text() { return (const void*)fText; } 73 size_t fByteLength; 74 const char* fText; 75 }; 76 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. 83 static SkBitmap shallow_copy(const SkBitmap& bitmap) { 84 return bitmap; 85 } 86 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 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