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 "SkPaintPriv.h" 12 #include "SkPatchUtils.h" 13 #include "SkPictureData.h" 14 #include "SkPicturePlayback.h" 15 #include "SkPictureRecord.h" 16 #include "SkReadBuffer.h" 17 #include "SkRSXform.h" 18 #include "SkSafeMath.h" 19 #include "SkTextBlob.h" 20 #include "SkTDArray.h" 21 #include "SkTypes.h" 22 23 // matches old SkCanvas::SaveFlags 24 enum LegacySaveFlags { 25 kHasAlphaLayer_LegacySaveFlags = 0x04, 26 kClipToLayer_LegacySaveFlags = 0x10, 27 }; 28 29 SkCanvas::SaveLayerFlags SkCanvas::LegacySaveFlagsToSaveLayerFlags(uint32_t flags) { 30 uint32_t layerFlags = 0; 31 32 if (0 == (flags & kClipToLayer_LegacySaveFlags)) { 33 layerFlags |= SkCanvas::kDontClipToLayer_PrivateSaveLayerFlag; 34 } 35 if (0 == (flags & kHasAlphaLayer_LegacySaveFlags)) { 36 layerFlags |= kIsOpaque_SaveLayerFlag; 37 } 38 return layerFlags; 39 } 40 41 /* 42 * Read the next op code and chunk size from 'reader'. The returned size 43 * is the entire size of the chunk (including the opcode). Thus, the 44 * offset just prior to calling ReadOpAndSize + 'size' is the offset 45 * to the next chunk's op code. This also means that the size of a chunk 46 * with no arguments (just an opcode) will be 4. 47 */ 48 DrawType SkPicturePlayback::ReadOpAndSize(SkReadBuffer* reader, uint32_t* size) { 49 uint32_t temp = reader->readInt(); 50 uint32_t op; 51 if (((uint8_t)temp) == temp) { 52 // old skp file - no size information 53 op = temp; 54 *size = 0; 55 } else { 56 UNPACK_8_24(temp, op, *size); 57 if (MASK_24 == *size) { 58 *size = reader->readInt(); 59 } 60 } 61 return (DrawType)op; 62 } 63 64 65 static const SkRect* get_rect_ptr(SkReadBuffer* reader, SkRect* storage) { 66 if (reader->readBool()) { 67 reader->readRect(storage); 68 return storage; 69 } else { 70 return nullptr; 71 } 72 } 73 74 class TextContainer { 75 public: 76 TextContainer(SkReadBuffer* reader, const SkPaint* paint) { 77 if (reader->validate(paint != nullptr)) { 78 fByteLength = reader->readInt(); 79 fText = (const char*)reader->skip(fByteLength); 80 if (reader->isValid()) { 81 if (fByteLength == 0) { 82 fCount = 0; 83 } else { 84 fCount = SkPaintPriv::ValidCountText(fText, fByteLength, paint->getTextEncoding()); 85 reader->validate(fCount > 0); 86 } 87 } 88 } 89 } 90 91 operator bool() const { return fCount >= 0; } 92 93 size_t length() const { return fByteLength; } 94 const void* text() const { return (const void*)fText; } 95 unsigned count() const { return fCount; } 96 97 private: 98 size_t fByteLength = 0; 99 const char* fText = nullptr; 100 int fCount = -1; 101 }; 102 103 void SkPicturePlayback::draw(SkCanvas* canvas, 104 SkPicture::AbortCallback* callback, 105 SkReadBuffer* buffer) { 106 AutoResetOpID aroi(this); 107 SkASSERT(0 == fCurOffset); 108 109 std::unique_ptr<SkReadBuffer> reader; 110 if (buffer) { 111 reader.reset(buffer->clone(fPictureData->opData()->bytes(), 112 fPictureData->opData()->size())); 113 } else { 114 reader.reset(new SkReadBuffer(fPictureData->opData()->bytes(), 115 fPictureData->opData()->size())); 116 } 117 118 // Record this, so we can concat w/ it if we encounter a setMatrix() 119 SkMatrix initialMatrix = canvas->getTotalMatrix(); 120 121 SkAutoCanvasRestore acr(canvas, false); 122 123 while (!reader->eof()) { 124 if (callback && callback->abort()) { 125 return; 126 } 127 128 fCurOffset = reader->offset(); 129 uint32_t size; 130 DrawType op = ReadOpAndSize(reader.get(), &size); 131 if (!reader->validate(op > UNUSED && op <= LAST_DRAWTYPE_ENUM)) { 132 return; 133 } 134 135 this->handleOp(reader.get(), op, size, canvas, initialMatrix); 136 } 137 138 // need to propagate invalid state to the parent reader 139 if (buffer) { 140 buffer->validate(reader->isValid()); 141 } 142 } 143 144 static void validate_offsetToRestore(SkReadBuffer* reader, size_t offsetToRestore) { 145 if (offsetToRestore) { 146 reader->validate(SkIsAlign4(offsetToRestore) && offsetToRestore >= reader->offset()); 147 } 148 } 149 150 void SkPicturePlayback::handleOp(SkReadBuffer* reader, 151 DrawType op, 152 uint32_t size, 153 SkCanvas* canvas, 154 const SkMatrix& initialMatrix) { 155 #define BREAK_ON_READ_ERROR(r) if (!r->isValid()) { break; } 156 157 switch (op) { 158 case NOOP: { 159 SkASSERT(size >= 4); 160 reader->skip(size - 4); 161 } break; 162 case FLUSH: 163 canvas->flush(); 164 break; 165 case CLIP_PATH: { 166 const SkPath& path = fPictureData->getPath(reader); 167 uint32_t packed = reader->readInt(); 168 SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed); 169 bool doAA = ClipParams_unpackDoAA(packed); 170 size_t offsetToRestore = reader->readInt(); 171 validate_offsetToRestore(reader, offsetToRestore); 172 BREAK_ON_READ_ERROR(reader); 173 174 canvas->clipPath(path, clipOp, doAA); 175 if (canvas->isClipEmpty() && offsetToRestore) { 176 reader->skip(offsetToRestore - reader->offset()); 177 } 178 } break; 179 case CLIP_REGION: { 180 SkRegion region; 181 reader->readRegion(®ion); 182 uint32_t packed = reader->readInt(); 183 SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed); 184 size_t offsetToRestore = reader->readInt(); 185 validate_offsetToRestore(reader, offsetToRestore); 186 BREAK_ON_READ_ERROR(reader); 187 188 canvas->clipRegion(region, clipOp); 189 if (canvas->isClipEmpty() && offsetToRestore) { 190 reader->skip(offsetToRestore - reader->offset()); 191 } 192 } break; 193 case CLIP_RECT: { 194 SkRect rect; 195 reader->readRect(&rect); 196 uint32_t packed = reader->readInt(); 197 SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed); 198 bool doAA = ClipParams_unpackDoAA(packed); 199 size_t offsetToRestore = reader->readInt(); 200 validate_offsetToRestore(reader, offsetToRestore); 201 BREAK_ON_READ_ERROR(reader); 202 203 canvas->clipRect(rect, clipOp, doAA); 204 if (canvas->isClipEmpty() && offsetToRestore) { 205 reader->skip(offsetToRestore - reader->offset()); 206 } 207 } break; 208 case CLIP_RRECT: { 209 SkRRect rrect; 210 reader->readRRect(&rrect); 211 uint32_t packed = reader->readInt(); 212 SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed); 213 bool doAA = ClipParams_unpackDoAA(packed); 214 size_t offsetToRestore = reader->readInt(); 215 validate_offsetToRestore(reader, offsetToRestore); 216 BREAK_ON_READ_ERROR(reader); 217 218 canvas->clipRRect(rrect, clipOp, doAA); 219 if (canvas->isClipEmpty() && offsetToRestore) { 220 reader->skip(offsetToRestore - reader->offset()); 221 } 222 } break; 223 case PUSH_CULL: break; // Deprecated, safe to ignore both push and pop. 224 case POP_CULL: break; 225 case CONCAT: { 226 SkMatrix matrix; 227 reader->readMatrix(&matrix); 228 BREAK_ON_READ_ERROR(reader); 229 230 canvas->concat(matrix); 231 break; 232 } 233 case DRAW_ANNOTATION: { 234 SkRect rect; 235 reader->readRect(&rect); 236 SkString key; 237 reader->readString(&key); 238 sk_sp<SkData> data = reader->readByteArrayAsData(); 239 BREAK_ON_READ_ERROR(reader); 240 241 canvas->drawAnnotation(rect, key.c_str(), data.get()); 242 } break; 243 case DRAW_ARC: { 244 const SkPaint* paint = fPictureData->getPaint(reader); 245 SkRect rect; 246 reader->readRect(&rect); 247 SkScalar startAngle = reader->readScalar(); 248 SkScalar sweepAngle = reader->readScalar(); 249 int useCenter = reader->readInt(); 250 BREAK_ON_READ_ERROR(reader); 251 252 if (paint) { 253 canvas->drawArc(rect, startAngle, sweepAngle, SkToBool(useCenter), *paint); 254 } 255 } break; 256 case DRAW_ATLAS: { 257 const SkPaint* paint = fPictureData->getPaint(reader); 258 const SkImage* atlas = fPictureData->getImage(reader); 259 const uint32_t flags = reader->readUInt(); 260 const int count = reader->readUInt(); 261 const SkRSXform* xform = (const SkRSXform*)reader->skip(count, sizeof(SkRSXform)); 262 const SkRect* tex = (const SkRect*)reader->skip(count, sizeof(SkRect)); 263 const SkColor* colors = nullptr; 264 SkBlendMode mode = SkBlendMode::kDst; 265 if (flags & DRAW_ATLAS_HAS_COLORS) { 266 colors = (const SkColor*)reader->skip(count, sizeof(SkColor)); 267 mode = (SkBlendMode)reader->readUInt(); 268 } 269 const SkRect* cull = nullptr; 270 if (flags & DRAW_ATLAS_HAS_CULL) { 271 cull = (const SkRect*)reader->skip(sizeof(SkRect)); 272 } 273 BREAK_ON_READ_ERROR(reader); 274 275 canvas->drawAtlas(atlas, xform, tex, colors, count, mode, cull, paint); 276 } break; 277 case DRAW_BITMAP: { 278 const SkPaint* paint = fPictureData->getPaint(reader); 279 const SkImage* image = fPictureData->getBitmapAsImage(reader); 280 SkPoint loc; 281 reader->readPoint(&loc); 282 BREAK_ON_READ_ERROR(reader); 283 284 canvas->drawImage(image, loc.fX, loc.fY, paint); 285 } break; 286 case DRAW_BITMAP_RECT: { 287 const SkPaint* paint = fPictureData->getPaint(reader); 288 const SkImage* image = fPictureData->getBitmapAsImage(reader); 289 SkRect storage; 290 const SkRect* src = get_rect_ptr(reader, &storage); // may be null 291 SkRect dst; 292 reader->readRect(&dst); // required 293 SkCanvas::SrcRectConstraint constraint = (SkCanvas::SrcRectConstraint)reader->readInt(); 294 BREAK_ON_READ_ERROR(reader); 295 296 if (src) { 297 canvas->drawImageRect(image, *src, dst, paint, constraint); 298 } else { 299 canvas->drawImageRect(image, dst, paint, constraint); 300 } 301 } break; 302 case DRAW_BITMAP_MATRIX: { 303 const SkPaint* paint = fPictureData->getPaint(reader); 304 const SkImage* image = fPictureData->getBitmapAsImage(reader); 305 SkMatrix matrix; 306 reader->readMatrix(&matrix); 307 BREAK_ON_READ_ERROR(reader); 308 309 SkAutoCanvasRestore acr(canvas, true); 310 canvas->concat(matrix); 311 canvas->drawImage(image, 0, 0, paint); 312 } break; 313 case DRAW_BITMAP_NINE: { 314 const SkPaint* paint = fPictureData->getPaint(reader); 315 const SkImage* image = fPictureData->getBitmapAsImage(reader); 316 SkIRect src; 317 reader->readIRect(&src); 318 SkRect dst; 319 reader->readRect(&dst); 320 BREAK_ON_READ_ERROR(reader); 321 322 canvas->drawImageNine(image, src, dst, paint); 323 } break; 324 case DRAW_CLEAR: { 325 auto c = reader->readInt(); 326 BREAK_ON_READ_ERROR(reader); 327 328 canvas->clear(c); 329 } break; 330 case DRAW_DATA: { 331 // This opcode is now dead, just need to skip it for backwards compatibility 332 size_t length = reader->readInt(); 333 (void)reader->skip(length); 334 // skip handles padding the read out to a multiple of 4 335 } break; 336 case DRAW_DRAWABLE: { 337 auto* d = fPictureData->getDrawable(reader); 338 BREAK_ON_READ_ERROR(reader); 339 340 canvas->drawDrawable(d); 341 } break; 342 case DRAW_DRAWABLE_MATRIX: { 343 SkMatrix matrix; 344 reader->readMatrix(&matrix); 345 SkDrawable* drawable = fPictureData->getDrawable(reader); 346 BREAK_ON_READ_ERROR(reader); 347 348 canvas->drawDrawable(drawable, &matrix); 349 } break; 350 case DRAW_DRRECT: { 351 const SkPaint* paint = fPictureData->getPaint(reader); 352 SkRRect outer, inner; 353 reader->readRRect(&outer); 354 reader->readRRect(&inner); 355 BREAK_ON_READ_ERROR(reader); 356 357 if (paint) { 358 canvas->drawDRRect(outer, inner, *paint); 359 } 360 } break; 361 case DRAW_IMAGE: { 362 const SkPaint* paint = fPictureData->getPaint(reader); 363 const SkImage* image = fPictureData->getImage(reader); 364 SkPoint loc; 365 reader->readPoint(&loc); 366 BREAK_ON_READ_ERROR(reader); 367 368 canvas->drawImage(image, loc.fX, loc.fY, paint); 369 } break; 370 case DRAW_IMAGE_LATTICE: { 371 const SkPaint* paint = fPictureData->getPaint(reader); 372 const SkImage* image = fPictureData->getImage(reader); 373 SkCanvas::Lattice lattice; 374 (void)SkCanvasPriv::ReadLattice(*reader, &lattice); 375 const SkRect* dst = reader->skipT<SkRect>(); 376 BREAK_ON_READ_ERROR(reader); 377 378 canvas->drawImageLattice(image, lattice, *dst, paint); 379 } break; 380 case DRAW_IMAGE_NINE: { 381 const SkPaint* paint = fPictureData->getPaint(reader); 382 const SkImage* image = fPictureData->getImage(reader); 383 SkIRect center; 384 reader->readIRect(¢er); 385 SkRect dst; 386 reader->readRect(&dst); 387 BREAK_ON_READ_ERROR(reader); 388 389 canvas->drawImageNine(image, center, dst, paint); 390 } break; 391 case DRAW_IMAGE_RECT: { 392 const SkPaint* paint = fPictureData->getPaint(reader); 393 const SkImage* image = fPictureData->getImage(reader); 394 SkRect storage; 395 const SkRect* src = get_rect_ptr(reader, &storage); // may be null 396 SkRect dst; 397 reader->readRect(&dst); // required 398 // DRAW_IMAGE_RECT_STRICT assumes this constraint, and doesn't store it 399 SkCanvas::SrcRectConstraint constraint = SkCanvas::kStrict_SrcRectConstraint; 400 if (DRAW_IMAGE_RECT == op) { 401 // newer op-code stores the constraint explicitly 402 constraint = (SkCanvas::SrcRectConstraint)reader->readInt(); 403 } 404 BREAK_ON_READ_ERROR(reader); 405 406 canvas->legacy_drawImageRect(image, src, dst, paint, constraint); 407 } break; 408 case DRAW_OVAL: { 409 const SkPaint* paint = fPictureData->getPaint(reader); 410 SkRect rect; 411 reader->readRect(&rect); 412 BREAK_ON_READ_ERROR(reader); 413 414 if (paint) { 415 canvas->drawOval(rect, *paint); 416 } 417 } break; 418 case DRAW_PAINT: { 419 const SkPaint* paint = fPictureData->getPaint(reader); 420 BREAK_ON_READ_ERROR(reader); 421 422 if (paint) { 423 canvas->drawPaint(*paint); 424 } 425 } break; 426 case DRAW_PATCH: { 427 const SkPaint* paint = fPictureData->getPaint(reader); 428 429 const SkPoint* cubics = (const SkPoint*)reader->skip(SkPatchUtils::kNumCtrlPts, 430 sizeof(SkPoint)); 431 uint32_t flag = reader->readInt(); 432 const SkColor* colors = nullptr; 433 if (flag & DRAW_VERTICES_HAS_COLORS) { 434 colors = (const SkColor*)reader->skip(SkPatchUtils::kNumCorners, sizeof(SkColor)); 435 } 436 const SkPoint* texCoords = nullptr; 437 if (flag & DRAW_VERTICES_HAS_TEXS) { 438 texCoords = (const SkPoint*)reader->skip(SkPatchUtils::kNumCorners, 439 sizeof(SkPoint)); 440 } 441 SkBlendMode bmode = SkBlendMode::kModulate; 442 if (flag & DRAW_VERTICES_HAS_XFER) { 443 unsigned mode = reader->readInt(); 444 if (mode <= (unsigned)SkBlendMode::kLastMode) { 445 bmode = (SkBlendMode)mode; 446 } 447 } 448 BREAK_ON_READ_ERROR(reader); 449 450 if (paint) { 451 canvas->drawPatch(cubics, colors, texCoords, bmode, *paint); 452 } 453 } break; 454 case DRAW_PATH: { 455 const SkPaint* paint = fPictureData->getPaint(reader); 456 const auto& path = fPictureData->getPath(reader); 457 BREAK_ON_READ_ERROR(reader); 458 459 if (paint) { 460 canvas->drawPath(path, *paint); 461 } 462 } break; 463 case DRAW_PICTURE: { 464 const auto* pic = fPictureData->getPicture(reader); 465 BREAK_ON_READ_ERROR(reader); 466 467 canvas->drawPicture(pic); 468 } break; 469 case DRAW_PICTURE_MATRIX_PAINT: { 470 const SkPaint* paint = fPictureData->getPaint(reader); 471 SkMatrix matrix; 472 reader->readMatrix(&matrix); 473 const SkPicture* pic = fPictureData->getPicture(reader); 474 BREAK_ON_READ_ERROR(reader); 475 476 canvas->drawPicture(pic, &matrix, paint); 477 } break; 478 case DRAW_POINTS: { 479 const SkPaint* paint = fPictureData->getPaint(reader); 480 SkCanvas::PointMode mode = (SkCanvas::PointMode)reader->readInt(); 481 size_t count = reader->readInt(); 482 const SkPoint* pts = (const SkPoint*)reader->skip(count, sizeof(SkPoint)); 483 BREAK_ON_READ_ERROR(reader); 484 485 if (paint) { 486 canvas->drawPoints(mode, count, pts, *paint); 487 } 488 } break; 489 case DRAW_POS_TEXT: { 490 const SkPaint* paint = fPictureData->getPaint(reader); 491 TextContainer text(reader, paint); 492 size_t points = reader->readInt(); 493 reader->validate(points == text.count()); 494 const SkPoint* pos = (const SkPoint*)reader->skip(points, sizeof(SkPoint)); 495 BREAK_ON_READ_ERROR(reader); 496 497 if (paint && text.text()) { 498 canvas->drawPosText(text.text(), text.length(), pos, *paint); 499 } 500 } break; 501 case DRAW_POS_TEXT_TOP_BOTTOM: { 502 const SkPaint* paint = fPictureData->getPaint(reader); 503 TextContainer text(reader, paint); 504 size_t points = reader->readInt(); 505 reader->validate(points == text.count()); 506 const SkPoint* pos = (const SkPoint*)reader->skip(points, sizeof(SkPoint)); 507 const SkScalar top = reader->readScalar(); 508 const SkScalar bottom = reader->readScalar(); 509 BREAK_ON_READ_ERROR(reader); 510 511 SkRect clip = canvas->getLocalClipBounds(); 512 if (top < clip.fBottom && bottom > clip.fTop && paint && text.text()) { 513 canvas->drawPosText(text.text(), text.length(), pos, *paint); 514 } 515 } break; 516 case DRAW_POS_TEXT_H: { 517 const SkPaint* paint = fPictureData->getPaint(reader); 518 TextContainer text(reader, paint); 519 size_t xCount = reader->readInt(); 520 reader->validate(xCount == text.count()); 521 const SkScalar constY = reader->readScalar(); 522 const SkScalar* xpos = (const SkScalar*)reader->skip(xCount, sizeof(SkScalar)); 523 BREAK_ON_READ_ERROR(reader); 524 525 if (paint && text.text()) { 526 canvas->drawPosTextH(text.text(), text.length(), xpos, constY, *paint); 527 } 528 } break; 529 case DRAW_POS_TEXT_H_TOP_BOTTOM: { 530 const SkPaint* paint = fPictureData->getPaint(reader); 531 TextContainer text(reader, paint); 532 size_t xCount = reader->readInt(); 533 reader->validate(xCount == text.count()); 534 const SkScalar* xpos = (const SkScalar*)reader->skip(SkSafeMath::Add(3, xCount), 535 sizeof(SkScalar)); 536 BREAK_ON_READ_ERROR(reader); 537 538 const SkScalar top = *xpos++; 539 const SkScalar bottom = *xpos++; 540 const SkScalar constY = *xpos++; 541 SkRect clip = canvas->getLocalClipBounds(); 542 if (top < clip.fBottom && bottom > clip.fTop && paint && text.text()) { 543 canvas->drawPosTextH(text.text(), text.length(), xpos, constY, *paint); 544 } 545 } break; 546 case DRAW_RECT: { 547 const SkPaint* paint = fPictureData->getPaint(reader); 548 SkRect rect; 549 reader->readRect(&rect); 550 BREAK_ON_READ_ERROR(reader); 551 552 if (paint) { 553 canvas->drawRect(rect, *paint); 554 } 555 } break; 556 case DRAW_REGION: { 557 const SkPaint* paint = fPictureData->getPaint(reader); 558 SkRegion region; 559 reader->readRegion(®ion); 560 BREAK_ON_READ_ERROR(reader); 561 562 if (paint) { 563 canvas->drawRegion(region, *paint); 564 } 565 } break; 566 case DRAW_RRECT: { 567 const SkPaint* paint = fPictureData->getPaint(reader); 568 SkRRect rrect; 569 reader->readRRect(&rrect); 570 BREAK_ON_READ_ERROR(reader); 571 572 if (paint) { 573 canvas->drawRRect(rrect, *paint); 574 } 575 } break; 576 case DRAW_SHADOW_REC: { 577 const auto& path = fPictureData->getPath(reader); 578 SkDrawShadowRec rec; 579 reader->readPoint3(&rec.fZPlaneParams); 580 reader->readPoint3(&rec.fLightPos); 581 rec.fLightRadius = reader->readScalar(); 582 if (reader->isVersionLT(SkReadBuffer::kTwoColorDrawShadow_Version)) { 583 SkScalar ambientAlpha = reader->readScalar(); 584 SkScalar spotAlpha = reader->readScalar(); 585 SkColor color = reader->read32(); 586 rec.fAmbientColor = SkColorSetA(color, SkColorGetA(color)*ambientAlpha); 587 rec.fSpotColor = SkColorSetA(color, SkColorGetA(color)*spotAlpha); 588 } else { 589 rec.fAmbientColor = reader->read32(); 590 rec.fSpotColor = reader->read32(); 591 } 592 rec.fFlags = reader->read32(); 593 BREAK_ON_READ_ERROR(reader); 594 595 canvas->private_draw_shadow_rec(path, rec); 596 } break; 597 case DRAW_SPRITE: { 598 /* const SkPaint* paint = */ fPictureData->getPaint(reader); 599 /* const SkImage* image = */ fPictureData->getBitmapAsImage(reader); 600 /* int left = */ reader->readInt(); 601 /* int top = */ reader->readInt(); 602 // drawSprite removed dec-2015 603 } break; 604 case DRAW_TEXT: { 605 const SkPaint* paint = fPictureData->getPaint(reader); 606 TextContainer text(reader, paint); 607 SkScalar x = reader->readScalar(); 608 SkScalar y = reader->readScalar(); 609 BREAK_ON_READ_ERROR(reader); 610 611 if (paint && text.text()) { 612 canvas->drawText(text.text(), text.length(), x, y, *paint); 613 } 614 } break; 615 case DRAW_TEXT_BLOB: { 616 const SkPaint* paint = fPictureData->getPaint(reader); 617 const SkTextBlob* blob = fPictureData->getTextBlob(reader); 618 SkScalar x = reader->readScalar(); 619 SkScalar y = reader->readScalar(); 620 BREAK_ON_READ_ERROR(reader); 621 622 if (paint) { 623 canvas->drawTextBlob(blob, x, y, *paint); 624 } 625 } break; 626 case DRAW_TEXT_TOP_BOTTOM: { 627 const SkPaint* paint = fPictureData->getPaint(reader); 628 TextContainer text(reader, paint); 629 const SkScalar* ptr = (const SkScalar*)reader->skip(4 * sizeof(SkScalar)); 630 BREAK_ON_READ_ERROR(reader); 631 632 // ptr[0] == x 633 // ptr[1] == y 634 // ptr[2] == top 635 // ptr[3] == bottom 636 SkRect clip = canvas->getLocalClipBounds(); 637 float top = ptr[2]; 638 float bottom = ptr[3]; 639 if (top < clip.fBottom && bottom > clip.fTop && paint && text.text()) { 640 canvas->drawText(text.text(), text.length(), ptr[0], ptr[1], *paint); 641 } 642 } break; 643 case DRAW_TEXT_ON_PATH: { 644 const SkPaint* paint = fPictureData->getPaint(reader); 645 TextContainer text(reader, paint); 646 const SkPath& path = fPictureData->getPath(reader); 647 SkMatrix matrix; 648 reader->readMatrix(&matrix); 649 BREAK_ON_READ_ERROR(reader); 650 651 if (paint && text.text()) { 652 canvas->drawTextOnPath(text.text(), text.length(), path, &matrix, *paint); 653 } 654 } break; 655 case DRAW_TEXT_RSXFORM: { 656 const SkPaint* paint = fPictureData->getPaint(reader); 657 uint32_t count = reader->readUInt(); 658 uint32_t flags = reader->readUInt(); 659 TextContainer text(reader, paint); 660 const SkRSXform* xform = (const SkRSXform*)reader->skip(count, sizeof(SkRSXform)); 661 const SkRect* cull = nullptr; 662 if (flags & DRAW_TEXT_RSXFORM_HAS_CULL) { 663 cull = (const SkRect*)reader->skip(sizeof(SkRect)); 664 } 665 reader->validate(count == text.count()); 666 BREAK_ON_READ_ERROR(reader); 667 668 if (text.text()) { 669 canvas->drawTextRSXform(text.text(), text.length(), xform, cull, *paint); 670 } 671 } break; 672 case DRAW_VERTICES_OBJECT: { 673 const SkPaint* paint = fPictureData->getPaint(reader); 674 const SkVertices* vertices = fPictureData->getVertices(reader); 675 SkBlendMode bmode = reader->read32LE(SkBlendMode::kLastMode); 676 BREAK_ON_READ_ERROR(reader); 677 678 if (paint && vertices) { 679 canvas->drawVertices(vertices, bmode, *paint); 680 } 681 } break; 682 case RESTORE: 683 canvas->restore(); 684 break; 685 case ROTATE: { 686 auto deg = reader->readScalar(); 687 canvas->rotate(deg); 688 } break; 689 case SAVE: 690 canvas->save(); 691 break; 692 case SAVE_LAYER_SAVEFLAGS_DEPRECATED: { 693 SkRect storage; 694 const SkRect* boundsPtr = get_rect_ptr(reader, &storage); 695 const SkPaint* paint = fPictureData->getPaint(reader); 696 auto flags = SkCanvas::LegacySaveFlagsToSaveLayerFlags(reader->readInt()); 697 BREAK_ON_READ_ERROR(reader); 698 699 canvas->saveLayer(SkCanvas::SaveLayerRec(boundsPtr, paint, flags)); 700 } break; 701 case SAVE_LAYER_SAVELAYERREC: { 702 SkCanvas::SaveLayerRec rec(nullptr, nullptr, nullptr, nullptr, nullptr, 0); 703 SkMatrix clipMatrix; 704 const uint32_t flatFlags = reader->readInt(); 705 SkRect bounds; 706 if (flatFlags & SAVELAYERREC_HAS_BOUNDS) { 707 reader->readRect(&bounds); 708 rec.fBounds = &bounds; 709 } 710 if (flatFlags & SAVELAYERREC_HAS_PAINT) { 711 rec.fPaint = fPictureData->getPaint(reader); 712 } 713 if (flatFlags & SAVELAYERREC_HAS_BACKDROP) { 714 if (const auto* paint = fPictureData->getPaint(reader)) { 715 rec.fBackdrop = paint->getImageFilter(); 716 } 717 } 718 if (flatFlags & SAVELAYERREC_HAS_FLAGS) { 719 rec.fSaveLayerFlags = reader->readInt(); 720 } 721 if (flatFlags & SAVELAYERREC_HAS_CLIPMASK) { 722 rec.fClipMask = fPictureData->getImage(reader); 723 } 724 if (flatFlags & SAVELAYERREC_HAS_CLIPMATRIX) { 725 reader->readMatrix(&clipMatrix); 726 rec.fClipMatrix = &clipMatrix; 727 } 728 BREAK_ON_READ_ERROR(reader); 729 730 canvas->saveLayer(rec); 731 } break; 732 case SCALE: { 733 SkScalar sx = reader->readScalar(); 734 SkScalar sy = reader->readScalar(); 735 canvas->scale(sx, sy); 736 } break; 737 case SET_MATRIX: { 738 SkMatrix matrix; 739 reader->readMatrix(&matrix); 740 matrix.postConcat(initialMatrix); 741 canvas->setMatrix(matrix); 742 } break; 743 case SKEW: { 744 SkScalar sx = reader->readScalar(); 745 SkScalar sy = reader->readScalar(); 746 canvas->skew(sx, sy); 747 } break; 748 case TRANSLATE: { 749 SkScalar dx = reader->readScalar(); 750 SkScalar dy = reader->readScalar(); 751 canvas->translate(dx, dy); 752 } break; 753 default: 754 reader->validate(false); // unknown op 755 break; 756 } 757 758 #undef BREAK_ON_READ_ERROR 759 } 760