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 "SkCanvasPriv.h" 10 #include "SkDrawShadowInfo.h" 11 #include "SkFontPriv.h" 12 #include "SkPaintPriv.h" 13 #include "SkPatchUtils.h" 14 #include "SkPictureData.h" 15 #include "SkPicturePlayback.h" 16 #include "SkPictureRecord.h" 17 #include "SkReadBuffer.h" 18 #include "SkRSXform.h" 19 #include "SkSafeMath.h" 20 #include "SkTextBlob.h" 21 #include "SkTDArray.h" 22 #include "SkTypes.h" 23 24 // matches old SkCanvas::SaveFlags 25 enum LegacySaveFlags { 26 kClipToLayer_LegacySaveFlags = 0x10, 27 }; 28 29 SkCanvas::SaveLayerFlags SkCanvasPriv::LegacySaveFlagsToSaveLayerFlags(uint32_t flags) { 30 uint32_t layerFlags = 0; 31 32 if (0 == (flags & kClipToLayer_LegacySaveFlags)) { 33 layerFlags |= kDontClipToLayer_SaveLayerFlag; 34 } 35 return layerFlags; 36 } 37 38 /* 39 * Read the next op code and chunk size from 'reader'. The returned size 40 * is the entire size of the chunk (including the opcode). Thus, the 41 * offset just prior to calling ReadOpAndSize + 'size' is the offset 42 * to the next chunk's op code. This also means that the size of a chunk 43 * with no arguments (just an opcode) will be 4. 44 */ 45 DrawType SkPicturePlayback::ReadOpAndSize(SkReadBuffer* reader, uint32_t* size) { 46 uint32_t temp = reader->readInt(); 47 uint32_t op; 48 if ((temp & 0xFF) == temp) { 49 // old skp file - no size information 50 op = temp; 51 *size = 0; 52 } else { 53 UNPACK_8_24(temp, op, *size); 54 if (MASK_24 == *size) { 55 *size = reader->readInt(); 56 } 57 } 58 return (DrawType)op; 59 } 60 61 62 static const SkRect* get_rect_ptr(SkReadBuffer* reader, SkRect* storage) { 63 if (reader->readBool()) { 64 reader->readRect(storage); 65 return storage; 66 } else { 67 return nullptr; 68 } 69 } 70 71 void SkPicturePlayback::draw(SkCanvas* canvas, 72 SkPicture::AbortCallback* callback, 73 SkReadBuffer* buffer) { 74 AutoResetOpID aroi(this); 75 SkASSERT(0 == fCurOffset); 76 77 SkReadBuffer reader(fPictureData->opData()->bytes(), 78 fPictureData->opData()->size()); 79 80 // Record this, so we can concat w/ it if we encounter a setMatrix() 81 SkMatrix initialMatrix = canvas->getTotalMatrix(); 82 83 SkAutoCanvasRestore acr(canvas, false); 84 85 while (!reader.eof()) { 86 if (callback && callback->abort()) { 87 return; 88 } 89 90 fCurOffset = reader.offset(); 91 uint32_t size; 92 DrawType op = ReadOpAndSize(&reader, &size); 93 if (!reader.validate(op > UNUSED && op <= LAST_DRAWTYPE_ENUM)) { 94 return; 95 } 96 97 this->handleOp(&reader, op, size, canvas, initialMatrix); 98 } 99 100 // need to propagate invalid state to the parent reader 101 if (buffer) { 102 buffer->validate(reader.isValid()); 103 } 104 } 105 106 static void validate_offsetToRestore(SkReadBuffer* reader, size_t offsetToRestore) { 107 if (offsetToRestore) { 108 reader->validate(SkIsAlign4(offsetToRestore) && offsetToRestore >= reader->offset()); 109 } 110 } 111 112 void SkPicturePlayback::handleOp(SkReadBuffer* reader, 113 DrawType op, 114 uint32_t size, 115 SkCanvas* canvas, 116 const SkMatrix& initialMatrix) { 117 #define BREAK_ON_READ_ERROR(r) if (!r->isValid()) break 118 119 switch (op) { 120 case NOOP: { 121 SkASSERT(size >= 4); 122 reader->skip(size - 4); 123 } break; 124 case FLUSH: 125 canvas->flush(); 126 break; 127 case CLIP_PATH: { 128 const SkPath& path = fPictureData->getPath(reader); 129 uint32_t packed = reader->readInt(); 130 SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed); 131 bool doAA = ClipParams_unpackDoAA(packed); 132 size_t offsetToRestore = reader->readInt(); 133 validate_offsetToRestore(reader, offsetToRestore); 134 BREAK_ON_READ_ERROR(reader); 135 136 canvas->clipPath(path, clipOp, doAA); 137 if (canvas->isClipEmpty() && offsetToRestore) { 138 reader->skip(offsetToRestore - reader->offset()); 139 } 140 } break; 141 case CLIP_REGION: { 142 SkRegion region; 143 reader->readRegion(®ion); 144 uint32_t packed = reader->readInt(); 145 SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed); 146 size_t offsetToRestore = reader->readInt(); 147 validate_offsetToRestore(reader, offsetToRestore); 148 BREAK_ON_READ_ERROR(reader); 149 150 canvas->clipRegion(region, clipOp); 151 if (canvas->isClipEmpty() && offsetToRestore) { 152 reader->skip(offsetToRestore - reader->offset()); 153 } 154 } break; 155 case CLIP_RECT: { 156 SkRect rect; 157 reader->readRect(&rect); 158 uint32_t packed = reader->readInt(); 159 SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed); 160 bool doAA = ClipParams_unpackDoAA(packed); 161 size_t offsetToRestore = reader->readInt(); 162 validate_offsetToRestore(reader, offsetToRestore); 163 BREAK_ON_READ_ERROR(reader); 164 165 canvas->clipRect(rect, clipOp, doAA); 166 if (canvas->isClipEmpty() && offsetToRestore) { 167 reader->skip(offsetToRestore - reader->offset()); 168 } 169 } break; 170 case CLIP_RRECT: { 171 SkRRect rrect; 172 reader->readRRect(&rrect); 173 uint32_t packed = reader->readInt(); 174 SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed); 175 bool doAA = ClipParams_unpackDoAA(packed); 176 size_t offsetToRestore = reader->readInt(); 177 validate_offsetToRestore(reader, offsetToRestore); 178 BREAK_ON_READ_ERROR(reader); 179 180 canvas->clipRRect(rrect, clipOp, doAA); 181 if (canvas->isClipEmpty() && offsetToRestore) { 182 reader->skip(offsetToRestore - reader->offset()); 183 } 184 } break; 185 case PUSH_CULL: break; // Deprecated, safe to ignore both push and pop. 186 case POP_CULL: break; 187 case CONCAT: { 188 SkMatrix matrix; 189 reader->readMatrix(&matrix); 190 BREAK_ON_READ_ERROR(reader); 191 192 canvas->concat(matrix); 193 break; 194 } 195 case DRAW_ANNOTATION: { 196 SkRect rect; 197 reader->readRect(&rect); 198 SkString key; 199 reader->readString(&key); 200 sk_sp<SkData> data = reader->readByteArrayAsData(); 201 BREAK_ON_READ_ERROR(reader); 202 SkASSERT(data); 203 204 canvas->drawAnnotation(rect, key.c_str(), data.get()); 205 } break; 206 case DRAW_ARC: { 207 const SkPaint* paint = fPictureData->getPaint(reader); 208 SkRect rect; 209 reader->readRect(&rect); 210 SkScalar startAngle = reader->readScalar(); 211 SkScalar sweepAngle = reader->readScalar(); 212 int useCenter = reader->readInt(); 213 BREAK_ON_READ_ERROR(reader); 214 215 if (paint) { 216 canvas->drawArc(rect, startAngle, sweepAngle, SkToBool(useCenter), *paint); 217 } 218 } break; 219 case DRAW_ATLAS: { 220 const SkPaint* paint = fPictureData->getPaint(reader); 221 const SkImage* atlas = fPictureData->getImage(reader); 222 const uint32_t flags = reader->readUInt(); 223 const int count = reader->readUInt(); 224 const SkRSXform* xform = (const SkRSXform*)reader->skip(count, sizeof(SkRSXform)); 225 const SkRect* tex = (const SkRect*)reader->skip(count, sizeof(SkRect)); 226 const SkColor* colors = nullptr; 227 SkBlendMode mode = SkBlendMode::kDst; 228 if (flags & DRAW_ATLAS_HAS_COLORS) { 229 colors = (const SkColor*)reader->skip(count, sizeof(SkColor)); 230 mode = (SkBlendMode)reader->readUInt(); 231 } 232 const SkRect* cull = nullptr; 233 if (flags & DRAW_ATLAS_HAS_CULL) { 234 cull = (const SkRect*)reader->skip(sizeof(SkRect)); 235 } 236 BREAK_ON_READ_ERROR(reader); 237 238 canvas->drawAtlas(atlas, xform, tex, colors, count, mode, cull, paint); 239 } break; 240 case DRAW_CLEAR: { 241 auto c = reader->readInt(); 242 BREAK_ON_READ_ERROR(reader); 243 244 canvas->clear(c); 245 } break; 246 case DRAW_DATA: { 247 // This opcode is now dead, just need to skip it for backwards compatibility 248 size_t length = reader->readInt(); 249 (void)reader->skip(length); 250 // skip handles padding the read out to a multiple of 4 251 } break; 252 case DRAW_DRAWABLE: { 253 auto* d = fPictureData->getDrawable(reader); 254 BREAK_ON_READ_ERROR(reader); 255 256 canvas->drawDrawable(d); 257 } break; 258 case DRAW_DRAWABLE_MATRIX: { 259 SkMatrix matrix; 260 reader->readMatrix(&matrix); 261 SkDrawable* drawable = fPictureData->getDrawable(reader); 262 BREAK_ON_READ_ERROR(reader); 263 264 canvas->drawDrawable(drawable, &matrix); 265 } break; 266 case DRAW_DRRECT: { 267 const SkPaint* paint = fPictureData->getPaint(reader); 268 SkRRect outer, inner; 269 reader->readRRect(&outer); 270 reader->readRRect(&inner); 271 BREAK_ON_READ_ERROR(reader); 272 273 if (paint) { 274 canvas->drawDRRect(outer, inner, *paint); 275 } 276 } break; 277 case DRAW_EDGEAA_RECT: { 278 SkRect rect; 279 reader->readRect(&rect); 280 SkCanvas::QuadAAFlags aaFlags = static_cast<SkCanvas::QuadAAFlags>(reader->read32()); 281 SkColor color = reader->read32(); 282 SkBlendMode blend = static_cast<SkBlendMode>(reader->read32()); 283 BREAK_ON_READ_ERROR(reader); 284 285 canvas->experimental_DrawEdgeAARectV1(rect, aaFlags, color, blend); 286 } break; 287 case DRAW_IMAGE: { 288 const SkPaint* paint = fPictureData->getPaint(reader); 289 const SkImage* image = fPictureData->getImage(reader); 290 SkPoint loc; 291 reader->readPoint(&loc); 292 BREAK_ON_READ_ERROR(reader); 293 294 canvas->drawImage(image, loc.fX, loc.fY, paint); 295 } break; 296 case DRAW_IMAGE_LATTICE: { 297 const SkPaint* paint = fPictureData->getPaint(reader); 298 const SkImage* image = fPictureData->getImage(reader); 299 SkCanvas::Lattice lattice; 300 (void)SkCanvasPriv::ReadLattice(*reader, &lattice); 301 const SkRect* dst = reader->skipT<SkRect>(); 302 BREAK_ON_READ_ERROR(reader); 303 304 canvas->drawImageLattice(image, lattice, *dst, paint); 305 } break; 306 case DRAW_IMAGE_NINE: { 307 const SkPaint* paint = fPictureData->getPaint(reader); 308 const SkImage* image = fPictureData->getImage(reader); 309 SkIRect center; 310 reader->readIRect(¢er); 311 SkRect dst; 312 reader->readRect(&dst); 313 BREAK_ON_READ_ERROR(reader); 314 315 canvas->drawImageNine(image, center, dst, paint); 316 } break; 317 case DRAW_IMAGE_RECT: { 318 const SkPaint* paint = fPictureData->getPaint(reader); 319 const SkImage* image = fPictureData->getImage(reader); 320 SkRect storage; 321 const SkRect* src = get_rect_ptr(reader, &storage); // may be null 322 SkRect dst; 323 reader->readRect(&dst); // required 324 // DRAW_IMAGE_RECT_STRICT assumes this constraint, and doesn't store it 325 SkCanvas::SrcRectConstraint constraint = SkCanvas::kStrict_SrcRectConstraint; 326 if (DRAW_IMAGE_RECT == op) { 327 // newer op-code stores the constraint explicitly 328 constraint = (SkCanvas::SrcRectConstraint)reader->readInt(); 329 } 330 BREAK_ON_READ_ERROR(reader); 331 332 canvas->legacy_drawImageRect(image, src, dst, paint, constraint); 333 } break; 334 case DRAW_IMAGE_SET: { 335 int cnt = reader->readInt(); 336 if (!reader->validate(cnt >= 0)) { 337 break; 338 } 339 SkFilterQuality filterQuality = (SkFilterQuality)reader->readUInt(); 340 SkBlendMode mode = (SkBlendMode)reader->readUInt(); 341 SkAutoTArray<SkCanvas::ImageSetEntry> set(cnt); 342 for (int i = 0; i < cnt; ++i) { 343 set[i].fImage = sk_ref_sp(fPictureData->getImage(reader)); 344 reader->readRect(&set[i].fSrcRect); 345 reader->readRect(&set[i].fDstRect); 346 set[i].fAlpha = reader->readScalar(); 347 set[i].fAAFlags = reader->readUInt(); 348 } 349 BREAK_ON_READ_ERROR(reader); 350 351 canvas->experimental_DrawImageSetV1(set.get(), cnt, filterQuality, mode); 352 } break; 353 case DRAW_OVAL: { 354 const SkPaint* paint = fPictureData->getPaint(reader); 355 SkRect rect; 356 reader->readRect(&rect); 357 BREAK_ON_READ_ERROR(reader); 358 359 if (paint) { 360 canvas->drawOval(rect, *paint); 361 } 362 } break; 363 case DRAW_PAINT: { 364 const SkPaint* paint = fPictureData->getPaint(reader); 365 BREAK_ON_READ_ERROR(reader); 366 367 if (paint) { 368 canvas->drawPaint(*paint); 369 } 370 } break; 371 case DRAW_BEHIND_PAINT: { 372 const SkPaint* paint = fPictureData->getPaint(reader); 373 BREAK_ON_READ_ERROR(reader); 374 375 if (paint) { 376 SkCanvasPriv::DrawBehind(canvas, *paint); 377 } 378 } break; 379 case DRAW_PATCH: { 380 const SkPaint* paint = fPictureData->getPaint(reader); 381 382 const SkPoint* cubics = (const SkPoint*)reader->skip(SkPatchUtils::kNumCtrlPts, 383 sizeof(SkPoint)); 384 uint32_t flag = reader->readInt(); 385 const SkColor* colors = nullptr; 386 if (flag & DRAW_VERTICES_HAS_COLORS) { 387 colors = (const SkColor*)reader->skip(SkPatchUtils::kNumCorners, sizeof(SkColor)); 388 } 389 const SkPoint* texCoords = nullptr; 390 if (flag & DRAW_VERTICES_HAS_TEXS) { 391 texCoords = (const SkPoint*)reader->skip(SkPatchUtils::kNumCorners, 392 sizeof(SkPoint)); 393 } 394 SkBlendMode bmode = SkBlendMode::kModulate; 395 if (flag & DRAW_VERTICES_HAS_XFER) { 396 unsigned mode = reader->readInt(); 397 if (mode <= (unsigned)SkBlendMode::kLastMode) { 398 bmode = (SkBlendMode)mode; 399 } 400 } 401 BREAK_ON_READ_ERROR(reader); 402 403 if (paint) { 404 canvas->drawPatch(cubics, colors, texCoords, bmode, *paint); 405 } 406 } break; 407 case DRAW_PATH: { 408 const SkPaint* paint = fPictureData->getPaint(reader); 409 const auto& path = fPictureData->getPath(reader); 410 BREAK_ON_READ_ERROR(reader); 411 412 if (paint) { 413 canvas->drawPath(path, *paint); 414 } 415 } break; 416 case DRAW_PICTURE: { 417 const auto* pic = fPictureData->getPicture(reader); 418 BREAK_ON_READ_ERROR(reader); 419 420 canvas->drawPicture(pic); 421 } break; 422 case DRAW_PICTURE_MATRIX_PAINT: { 423 const SkPaint* paint = fPictureData->getPaint(reader); 424 SkMatrix matrix; 425 reader->readMatrix(&matrix); 426 const SkPicture* pic = fPictureData->getPicture(reader); 427 BREAK_ON_READ_ERROR(reader); 428 429 canvas->drawPicture(pic, &matrix, paint); 430 } break; 431 case DRAW_POINTS: { 432 const SkPaint* paint = fPictureData->getPaint(reader); 433 SkCanvas::PointMode mode = (SkCanvas::PointMode)reader->readInt(); 434 size_t count = reader->readInt(); 435 const SkPoint* pts = (const SkPoint*)reader->skip(count, sizeof(SkPoint)); 436 BREAK_ON_READ_ERROR(reader); 437 438 if (paint) { 439 canvas->drawPoints(mode, count, pts, *paint); 440 } 441 } break; 442 case DRAW_RECT: { 443 const SkPaint* paint = fPictureData->getPaint(reader); 444 SkRect rect; 445 reader->readRect(&rect); 446 BREAK_ON_READ_ERROR(reader); 447 448 if (paint) { 449 canvas->drawRect(rect, *paint); 450 } 451 } break; 452 case DRAW_REGION: { 453 const SkPaint* paint = fPictureData->getPaint(reader); 454 SkRegion region; 455 reader->readRegion(®ion); 456 BREAK_ON_READ_ERROR(reader); 457 458 if (paint) { 459 canvas->drawRegion(region, *paint); 460 } 461 } break; 462 case DRAW_RRECT: { 463 const SkPaint* paint = fPictureData->getPaint(reader); 464 SkRRect rrect; 465 reader->readRRect(&rrect); 466 BREAK_ON_READ_ERROR(reader); 467 468 if (paint) { 469 canvas->drawRRect(rrect, *paint); 470 } 471 } break; 472 case DRAW_SHADOW_REC: { 473 const auto& path = fPictureData->getPath(reader); 474 SkDrawShadowRec rec; 475 reader->readPoint3(&rec.fZPlaneParams); 476 reader->readPoint3(&rec.fLightPos); 477 rec.fLightRadius = reader->readScalar(); 478 if (reader->isVersionLT(SkReadBuffer::kTwoColorDrawShadow_Version)) { 479 SkScalar ambientAlpha = reader->readScalar(); 480 SkScalar spotAlpha = reader->readScalar(); 481 SkColor color = reader->read32(); 482 rec.fAmbientColor = SkColorSetA(color, SkColorGetA(color)*ambientAlpha); 483 rec.fSpotColor = SkColorSetA(color, SkColorGetA(color)*spotAlpha); 484 } else { 485 rec.fAmbientColor = reader->read32(); 486 rec.fSpotColor = reader->read32(); 487 } 488 rec.fFlags = reader->read32(); 489 BREAK_ON_READ_ERROR(reader); 490 491 canvas->private_draw_shadow_rec(path, rec); 492 } break; 493 case DRAW_TEXT_BLOB: { 494 const SkPaint* paint = fPictureData->getPaint(reader); 495 const SkTextBlob* blob = fPictureData->getTextBlob(reader); 496 SkScalar x = reader->readScalar(); 497 SkScalar y = reader->readScalar(); 498 BREAK_ON_READ_ERROR(reader); 499 500 if (paint) { 501 canvas->drawTextBlob(blob, x, y, *paint); 502 } 503 } break; 504 case DRAW_VERTICES_OBJECT: { 505 const SkPaint* paint = fPictureData->getPaint(reader); 506 const SkVertices* vertices = fPictureData->getVertices(reader); 507 const int boneCount = reader->readInt(); 508 const SkVertices::Bone* bones = boneCount ? 509 (const SkVertices::Bone*) reader->skip(boneCount, sizeof(SkVertices::Bone)) : 510 nullptr; 511 SkBlendMode bmode = reader->read32LE(SkBlendMode::kLastMode); 512 BREAK_ON_READ_ERROR(reader); 513 514 if (paint && vertices) { 515 canvas->drawVertices(vertices, bones, boneCount, bmode, *paint); 516 } 517 } break; 518 case RESTORE: 519 canvas->restore(); 520 break; 521 case ROTATE: { 522 auto deg = reader->readScalar(); 523 canvas->rotate(deg); 524 } break; 525 case SAVE: 526 canvas->save(); 527 break; 528 case SAVE_BEHIND: { 529 uint32_t flags = reader->readInt(); 530 const SkRect* subset = nullptr; 531 SkRect storage; 532 if (flags & SAVEBEHIND_HAS_SUBSET) { 533 reader->readRect(&storage); 534 subset = &storage; 535 } 536 SkCanvasPriv::SaveBehind(canvas, subset); 537 } break; 538 case SAVE_LAYER_SAVEFLAGS_DEPRECATED: { 539 SkRect storage; 540 const SkRect* boundsPtr = get_rect_ptr(reader, &storage); 541 const SkPaint* paint = fPictureData->getPaint(reader); 542 auto flags = SkCanvasPriv::LegacySaveFlagsToSaveLayerFlags(reader->readInt()); 543 BREAK_ON_READ_ERROR(reader); 544 545 canvas->saveLayer(SkCanvas::SaveLayerRec(boundsPtr, paint, flags)); 546 } break; 547 case SAVE_LAYER_SAVELAYERREC: { 548 SkCanvas::SaveLayerRec rec(nullptr, nullptr, nullptr, nullptr, nullptr, 0); 549 SkMatrix clipMatrix; 550 const uint32_t flatFlags = reader->readInt(); 551 SkRect bounds; 552 if (flatFlags & SAVELAYERREC_HAS_BOUNDS) { 553 reader->readRect(&bounds); 554 rec.fBounds = &bounds; 555 } 556 if (flatFlags & SAVELAYERREC_HAS_PAINT) { 557 rec.fPaint = fPictureData->getPaint(reader); 558 } 559 if (flatFlags & SAVELAYERREC_HAS_BACKDROP) { 560 if (const auto* paint = fPictureData->getPaint(reader)) { 561 rec.fBackdrop = paint->getImageFilter(); 562 } 563 } 564 if (flatFlags & SAVELAYERREC_HAS_FLAGS) { 565 rec.fSaveLayerFlags = reader->readInt(); 566 } 567 if (flatFlags & SAVELAYERREC_HAS_CLIPMASK) { 568 rec.fClipMask = fPictureData->getImage(reader); 569 } 570 if (flatFlags & SAVELAYERREC_HAS_CLIPMATRIX) { 571 reader->readMatrix(&clipMatrix); 572 rec.fClipMatrix = &clipMatrix; 573 } 574 BREAK_ON_READ_ERROR(reader); 575 576 canvas->saveLayer(rec); 577 } break; 578 case SCALE: { 579 SkScalar sx = reader->readScalar(); 580 SkScalar sy = reader->readScalar(); 581 canvas->scale(sx, sy); 582 } break; 583 case SET_MATRIX: { 584 SkMatrix matrix; 585 reader->readMatrix(&matrix); 586 matrix.postConcat(initialMatrix); 587 canvas->setMatrix(matrix); 588 } break; 589 case SKEW: { 590 SkScalar sx = reader->readScalar(); 591 SkScalar sy = reader->readScalar(); 592 canvas->skew(sx, sy); 593 } break; 594 case TRANSLATE: { 595 SkScalar dx = reader->readScalar(); 596 SkScalar dy = reader->readScalar(); 597 canvas->translate(dx, dy); 598 } break; 599 default: 600 reader->validate(false); // unknown op 601 break; 602 } 603 604 #undef BREAK_ON_READ_ERROR 605 } 606