1 /* 2 * Copyright 2011 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 "SkPictureRecord.h" 9 #include "SkDrawShadowRec.h" 10 #include "SkImage_Base.h" 11 #include "SkPatchUtils.h" 12 #include "SkPixelRef.h" 13 #include "SkRRect.h" 14 #include "SkRSXform.h" 15 #include "SkTextBlob.h" 16 #include "SkTSearch.h" 17 #include "SkClipOpPriv.h" 18 19 #define HEAP_BLOCK_SIZE 4096 20 21 enum { 22 // just need a value that save or getSaveCount would never return 23 kNoInitialSave = -1, 24 }; 25 26 // A lot of basic types get stored as a uint32_t: bools, ints, paint indices, etc. 27 static int const kUInt32Size = 4; 28 29 SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags) 30 : INHERITED(dimensions.width(), dimensions.height()) 31 , fRecordFlags(flags) 32 , fInitialSaveCount(kNoInitialSave) { 33 } 34 35 SkPictureRecord::~SkPictureRecord() { 36 fImageRefs.unrefAll(); 37 fPictureRefs.unrefAll(); 38 fDrawableRefs.unrefAll(); 39 fTextBlobRefs.unrefAll(); 40 fVerticesRefs.unrefAll(); 41 } 42 43 /////////////////////////////////////////////////////////////////////////////// 44 45 void SkPictureRecord::willSave() { 46 // record the offset to us, making it non-positive to distinguish a save 47 // from a clip entry. 48 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten()); 49 this->recordSave(); 50 51 this->INHERITED::willSave(); 52 } 53 54 void SkPictureRecord::recordSave() { 55 fContentInfo.onSave(); 56 57 // op only 58 size_t size = sizeof(kUInt32Size); 59 size_t initialOffset = this->addDraw(SAVE, &size); 60 61 this->validate(initialOffset, size); 62 } 63 64 SkCanvas::SaveLayerStrategy SkPictureRecord::getSaveLayerStrategy(const SaveLayerRec& rec) { 65 // record the offset to us, making it non-positive to distinguish a save 66 // from a clip entry. 67 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten()); 68 this->recordSaveLayer(rec); 69 70 (void)this->INHERITED::getSaveLayerStrategy(rec); 71 /* No need for a (potentially very big) layer which we don't actually need 72 at this time (and may not be able to afford since during record our 73 clip starts out the size of the picture, which is often much larger 74 than the size of the actual device we'll use during playback). 75 */ 76 return kNoLayer_SaveLayerStrategy; 77 } 78 79 void SkPictureRecord::recordSaveLayer(const SaveLayerRec& rec) { 80 fContentInfo.onSaveLayer(); 81 82 // op + flatflags 83 size_t size = 2 * kUInt32Size; 84 uint32_t flatFlags = 0; 85 86 if (rec.fBounds) { 87 flatFlags |= SAVELAYERREC_HAS_BOUNDS; 88 size += sizeof(*rec.fBounds); 89 } 90 if (rec.fPaint) { 91 flatFlags |= SAVELAYERREC_HAS_PAINT; 92 size += sizeof(uint32_t); // index 93 } 94 if (rec.fBackdrop) { 95 flatFlags |= SAVELAYERREC_HAS_BACKDROP; 96 size += sizeof(uint32_t); // (paint) index 97 } 98 if (rec.fSaveLayerFlags) { 99 flatFlags |= SAVELAYERREC_HAS_FLAGS; 100 size += sizeof(uint32_t); 101 } 102 if (rec.fClipMask) { 103 flatFlags |= SAVELAYERREC_HAS_CLIPMASK; 104 size += sizeof(uint32_t); // clip image index 105 } 106 if (rec.fClipMatrix) { 107 flatFlags |= SAVELAYERREC_HAS_CLIPMATRIX; 108 size += rec.fClipMatrix->writeToMemory(nullptr); 109 } 110 111 const size_t initialOffset = this->addDraw(SAVE_LAYER_SAVELAYERREC, &size); 112 this->addInt(flatFlags); 113 if (flatFlags & SAVELAYERREC_HAS_BOUNDS) { 114 this->addRect(*rec.fBounds); 115 } 116 if (flatFlags & SAVELAYERREC_HAS_PAINT) { 117 this->addPaintPtr(rec.fPaint); 118 } 119 if (flatFlags & SAVELAYERREC_HAS_BACKDROP) { 120 // overkill, but we didn't already track single flattenables, so using a paint for that 121 SkPaint paint; 122 paint.setImageFilter(sk_ref_sp(const_cast<SkImageFilter*>(rec.fBackdrop))); 123 this->addPaint(paint); 124 } 125 if (flatFlags & SAVELAYERREC_HAS_FLAGS) { 126 this->addInt(rec.fSaveLayerFlags); 127 } 128 if (flatFlags & SAVELAYERREC_HAS_CLIPMASK) { 129 this->addImage(rec.fClipMask); 130 } 131 if (flatFlags & SAVELAYERREC_HAS_CLIPMATRIX) { 132 this->addMatrix(*rec.fClipMatrix); 133 } 134 this->validate(initialOffset, size); 135 } 136 137 #ifdef SK_DEBUG 138 /* 139 * Read the op code from 'offset' in 'writer' and extract the size too. 140 */ 141 static DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* size) { 142 uint32_t peek = writer->readTAt<uint32_t>(offset); 143 144 uint32_t op; 145 UNPACK_8_24(peek, op, *size); 146 if (MASK_24 == *size) { 147 // size required its own slot right after the op code 148 *size = writer->readTAt<uint32_t>(offset + kUInt32Size); 149 } 150 return (DrawType) op; 151 } 152 #endif//SK_DEBUG 153 154 void SkPictureRecord::willRestore() { 155 #if 0 156 SkASSERT(fRestoreOffsetStack.count() > 1); 157 #endif 158 159 // check for underflow 160 if (fRestoreOffsetStack.count() == 0) { 161 return; 162 } 163 164 this->recordRestore(); 165 166 fRestoreOffsetStack.pop(); 167 168 this->INHERITED::willRestore(); 169 } 170 171 void SkPictureRecord::recordRestore(bool fillInSkips) { 172 fContentInfo.onRestore(); 173 174 if (fillInSkips) { 175 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten()); 176 } 177 size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code 178 size_t initialOffset = this->addDraw(RESTORE, &size); 179 this->validate(initialOffset, size); 180 } 181 182 void SkPictureRecord::recordTranslate(const SkMatrix& m) { 183 SkASSERT(SkMatrix::kTranslate_Mask == m.getType()); 184 185 // op + dx + dy 186 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar); 187 size_t initialOffset = this->addDraw(TRANSLATE, &size); 188 this->addScalar(m.getTranslateX()); 189 this->addScalar(m.getTranslateY()); 190 this->validate(initialOffset, size); 191 } 192 193 void SkPictureRecord::recordScale(const SkMatrix& m) { 194 SkASSERT(SkMatrix::kScale_Mask == m.getType()); 195 196 // op + sx + sy 197 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar); 198 size_t initialOffset = this->addDraw(SCALE, &size); 199 this->addScalar(m.getScaleX()); 200 this->addScalar(m.getScaleY()); 201 this->validate(initialOffset, size); 202 } 203 204 void SkPictureRecord::didConcat(const SkMatrix& matrix) { 205 switch (matrix.getType()) { 206 case SkMatrix::kTranslate_Mask: 207 this->recordTranslate(matrix); 208 break; 209 case SkMatrix::kScale_Mask: 210 this->recordScale(matrix); 211 break; 212 default: 213 this->recordConcat(matrix); 214 break; 215 } 216 this->INHERITED::didConcat(matrix); 217 } 218 219 void SkPictureRecord::recordConcat(const SkMatrix& matrix) { 220 this->validate(fWriter.bytesWritten(), 0); 221 // op + matrix 222 size_t size = kUInt32Size + matrix.writeToMemory(nullptr); 223 size_t initialOffset = this->addDraw(CONCAT, &size); 224 this->addMatrix(matrix); 225 this->validate(initialOffset, size); 226 } 227 228 void SkPictureRecord::didSetMatrix(const SkMatrix& matrix) { 229 this->validate(fWriter.bytesWritten(), 0); 230 // op + matrix 231 size_t size = kUInt32Size + matrix.writeToMemory(nullptr); 232 size_t initialOffset = this->addDraw(SET_MATRIX, &size); 233 this->addMatrix(matrix); 234 this->validate(initialOffset, size); 235 this->INHERITED::didSetMatrix(matrix); 236 } 237 238 static bool clipOpExpands(SkClipOp op) { 239 switch (op) { 240 case kUnion_SkClipOp: 241 case kXOR_SkClipOp: 242 case kReverseDifference_SkClipOp: 243 case kReplace_SkClipOp: 244 return true; 245 case kIntersect_SkClipOp: 246 case kDifference_SkClipOp: 247 return false; 248 default: 249 SkDEBUGFAIL("unknown clipop"); 250 return false; 251 } 252 } 253 254 void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) { 255 int32_t offset = fRestoreOffsetStack.top(); 256 while (offset > 0) { 257 uint32_t peek = fWriter.readTAt<uint32_t>(offset); 258 fWriter.overwriteTAt(offset, restoreOffset); 259 offset = peek; 260 } 261 262 #ifdef SK_DEBUG 263 // offset of 0 has been disabled, so we skip it 264 if (offset > 0) { 265 // assert that the final offset value points to a save verb 266 uint32_t opSize; 267 DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize); 268 SkASSERT(SAVE_LAYER_SAVEFLAGS_DEPRECATED != drawOp); 269 SkASSERT(SAVE_LAYER_SAVELAYERFLAGS_DEPRECATED_JAN_2016 != drawOp); 270 SkASSERT(SAVE == drawOp || SAVE_LAYER_SAVELAYERREC == drawOp); 271 } 272 #endif 273 } 274 275 void SkPictureRecord::beginRecording() { 276 // we have to call this *after* our constructor, to ensure that it gets 277 // recorded. This is balanced by restoreToCount() call from endRecording, 278 // which in-turn calls our overridden restore(), so those get recorded too. 279 fInitialSaveCount = this->save(); 280 } 281 282 void SkPictureRecord::endRecording() { 283 SkASSERT(kNoInitialSave != fInitialSaveCount); 284 this->restoreToCount(fInitialSaveCount); 285 } 286 287 size_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkClipOp op) { 288 if (fRestoreOffsetStack.isEmpty()) { 289 return -1; 290 } 291 292 // The RestoreOffset field is initially filled with a placeholder 293 // value that points to the offset of the previous RestoreOffset 294 // in the current stack level, thus forming a linked list so that 295 // the restore offsets can be filled in when the corresponding 296 // restore command is recorded. 297 int32_t prevOffset = fRestoreOffsetStack.top(); 298 299 if (clipOpExpands(op)) { 300 // Run back through any previous clip ops, and mark their offset to 301 // be 0, disabling their ability to trigger a jump-to-restore, otherwise 302 // they could hide this clips ability to expand the clip (i.e. go from 303 // empty to non-empty). 304 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0); 305 306 // Reset the pointer back to the previous clip so that subsequent 307 // restores don't overwrite the offsets we just cleared. 308 prevOffset = 0; 309 } 310 311 size_t offset = fWriter.bytesWritten(); 312 this->addInt(prevOffset); 313 fRestoreOffsetStack.top() = SkToU32(offset); 314 return offset; 315 } 316 317 void SkPictureRecord::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) { 318 this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle); 319 this->INHERITED::onClipRect(rect, op, edgeStyle); 320 } 321 322 size_t SkPictureRecord::recordClipRect(const SkRect& rect, SkClipOp op, bool doAA) { 323 // id + rect + clip params 324 size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size; 325 // recordRestoreOffsetPlaceholder doesn't always write an offset 326 if (!fRestoreOffsetStack.isEmpty()) { 327 // + restore offset 328 size += kUInt32Size; 329 } 330 size_t initialOffset = this->addDraw(CLIP_RECT, &size); 331 this->addRect(rect); 332 this->addInt(ClipParams_pack(op, doAA)); 333 size_t offset = this->recordRestoreOffsetPlaceholder(op); 334 335 this->validate(initialOffset, size); 336 return offset; 337 } 338 339 void SkPictureRecord::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) { 340 this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle); 341 this->INHERITED::onClipRRect(rrect, op, edgeStyle); 342 } 343 344 size_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkClipOp op, bool doAA) { 345 // op + rrect + clip params 346 size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size; 347 // recordRestoreOffsetPlaceholder doesn't always write an offset 348 if (!fRestoreOffsetStack.isEmpty()) { 349 // + restore offset 350 size += kUInt32Size; 351 } 352 size_t initialOffset = this->addDraw(CLIP_RRECT, &size); 353 this->addRRect(rrect); 354 this->addInt(ClipParams_pack(op, doAA)); 355 size_t offset = recordRestoreOffsetPlaceholder(op); 356 this->validate(initialOffset, size); 357 return offset; 358 } 359 360 void SkPictureRecord::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) { 361 int pathID = this->addPathToHeap(path); 362 this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle); 363 this->INHERITED::onClipPath(path, op, edgeStyle); 364 } 365 366 size_t SkPictureRecord::recordClipPath(int pathID, SkClipOp op, bool doAA) { 367 // op + path index + clip params 368 size_t size = 3 * kUInt32Size; 369 // recordRestoreOffsetPlaceholder doesn't always write an offset 370 if (!fRestoreOffsetStack.isEmpty()) { 371 // + restore offset 372 size += kUInt32Size; 373 } 374 size_t initialOffset = this->addDraw(CLIP_PATH, &size); 375 this->addInt(pathID); 376 this->addInt(ClipParams_pack(op, doAA)); 377 size_t offset = recordRestoreOffsetPlaceholder(op); 378 this->validate(initialOffset, size); 379 return offset; 380 } 381 382 void SkPictureRecord::onClipRegion(const SkRegion& region, SkClipOp op) { 383 this->recordClipRegion(region, op); 384 this->INHERITED::onClipRegion(region, op); 385 } 386 387 size_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkClipOp op) { 388 // op + clip params + region 389 size_t size = 2 * kUInt32Size + region.writeToMemory(nullptr); 390 // recordRestoreOffsetPlaceholder doesn't always write an offset 391 if (!fRestoreOffsetStack.isEmpty()) { 392 // + restore offset 393 size += kUInt32Size; 394 } 395 size_t initialOffset = this->addDraw(CLIP_REGION, &size); 396 this->addRegion(region); 397 this->addInt(ClipParams_pack(op, false)); 398 size_t offset = this->recordRestoreOffsetPlaceholder(op); 399 400 this->validate(initialOffset, size); 401 return offset; 402 } 403 404 void SkPictureRecord::onDrawPaint(const SkPaint& paint) { 405 // op + paint index 406 size_t size = 2 * kUInt32Size; 407 size_t initialOffset = this->addDraw(DRAW_PAINT, &size); 408 this->addPaint(paint); 409 this->validate(initialOffset, size); 410 } 411 412 void SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[], 413 const SkPaint& paint) { 414 fContentInfo.onDrawPoints(count, paint); 415 416 // op + paint index + mode + count + point data 417 size_t size = 4 * kUInt32Size + count * sizeof(SkPoint); 418 size_t initialOffset = this->addDraw(DRAW_POINTS, &size); 419 this->addPaint(paint); 420 421 this->addInt(mode); 422 this->addInt(SkToInt(count)); 423 fWriter.writeMul4(pts, count * sizeof(SkPoint)); 424 this->validate(initialOffset, size); 425 } 426 427 void SkPictureRecord::onDrawOval(const SkRect& oval, const SkPaint& paint) { 428 // op + paint index + rect 429 size_t size = 2 * kUInt32Size + sizeof(oval); 430 size_t initialOffset = this->addDraw(DRAW_OVAL, &size); 431 this->addPaint(paint); 432 this->addRect(oval); 433 this->validate(initialOffset, size); 434 } 435 436 void SkPictureRecord::onDrawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, 437 bool useCenter, const SkPaint& paint) { 438 // op + paint index + rect + start + sweep + bool (as int) 439 size_t size = 2 * kUInt32Size + sizeof(oval) + sizeof(startAngle) + sizeof(sweepAngle) + 440 sizeof(int); 441 size_t initialOffset = this->addDraw(DRAW_ARC, &size); 442 this->addPaint(paint); 443 this->addRect(oval); 444 this->addScalar(startAngle); 445 this->addScalar(sweepAngle); 446 this->addInt(useCenter); 447 this->validate(initialOffset, size); 448 } 449 450 void SkPictureRecord::onDrawRect(const SkRect& rect, const SkPaint& paint) { 451 // op + paint index + rect 452 size_t size = 2 * kUInt32Size + sizeof(rect); 453 size_t initialOffset = this->addDraw(DRAW_RECT, &size); 454 this->addPaint(paint); 455 this->addRect(rect); 456 this->validate(initialOffset, size); 457 } 458 459 void SkPictureRecord::onDrawRegion(const SkRegion& region, const SkPaint& paint) { 460 // op + paint index + region 461 size_t regionBytes = region.writeToMemory(nullptr); 462 size_t size = 2 * kUInt32Size + regionBytes; 463 size_t initialOffset = this->addDraw(DRAW_REGION, &size); 464 this->addPaint(paint); 465 fWriter.writeRegion(region); 466 this->validate(initialOffset, size); 467 } 468 469 void SkPictureRecord::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) { 470 // op + paint index + rrect 471 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory; 472 size_t initialOffset = this->addDraw(DRAW_RRECT, &size); 473 this->addPaint(paint); 474 this->addRRect(rrect); 475 this->validate(initialOffset, size); 476 } 477 478 void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, 479 const SkPaint& paint) { 480 // op + paint index + rrects 481 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2; 482 size_t initialOffset = this->addDraw(DRAW_DRRECT, &size); 483 this->addPaint(paint); 484 this->addRRect(outer); 485 this->addRRect(inner); 486 this->validate(initialOffset, size); 487 } 488 489 void SkPictureRecord::onDrawPath(const SkPath& path, const SkPaint& paint) { 490 fContentInfo.onDrawPath(path, paint); 491 492 // op + paint index + path index 493 size_t size = 3 * kUInt32Size; 494 size_t initialOffset = this->addDraw(DRAW_PATH, &size); 495 this->addPaint(paint); 496 this->addPath(path); 497 this->validate(initialOffset, size); 498 } 499 500 void SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, 501 const SkPaint* paint) { 502 // op + paint_index + image_index + x + y 503 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar); 504 size_t initialOffset = this->addDraw(DRAW_IMAGE, &size); 505 this->addPaintPtr(paint); 506 this->addImage(image); 507 this->addScalar(x); 508 this->addScalar(y); 509 this->validate(initialOffset, size); 510 } 511 512 void SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst, 513 const SkPaint* paint, SrcRectConstraint constraint) { 514 // id + paint_index + image_index + bool_for_src + constraint 515 size_t size = 5 * kUInt32Size; 516 if (src) { 517 size += sizeof(*src); // + rect 518 } 519 size += sizeof(dst); // + rect 520 521 size_t initialOffset = this->addDraw(DRAW_IMAGE_RECT, &size); 522 this->addPaintPtr(paint); 523 this->addImage(image); 524 this->addRectPtr(src); // may be null 525 this->addRect(dst); 526 this->addInt(constraint); 527 this->validate(initialOffset, size); 528 } 529 530 void SkPictureRecord::onDrawImageNine(const SkImage* img, const SkIRect& center, const SkRect& dst, 531 const SkPaint* paint) { 532 // id + paint_index + image_index + center + dst 533 size_t size = 3 * kUInt32Size + sizeof(SkIRect) + sizeof(SkRect); 534 535 size_t initialOffset = this->addDraw(DRAW_IMAGE_NINE, &size); 536 this->addPaintPtr(paint); 537 this->addImage(img); 538 this->addIRect(center); 539 this->addRect(dst); 540 this->validate(initialOffset, size); 541 } 542 543 void SkPictureRecord::onDrawImageLattice(const SkImage* image, const Lattice& lattice, 544 const SkRect& dst, const SkPaint* paint) { 545 // xCount + xDivs + yCount+ yDivs 546 int flagCount = (nullptr == lattice.fFlags) ? 0 : (lattice.fXCount + 1) * (lattice.fYCount + 1); 547 size_t latticeSize = (1 + lattice.fXCount + 1 + lattice.fYCount + 1) * kUInt32Size + 548 SkAlign4(flagCount * sizeof(SkCanvas::Lattice::Flags)) + sizeof(SkIRect); 549 550 // op + paint index + image index + lattice + dst rect 551 size_t size = 3 * kUInt32Size + latticeSize + sizeof(dst); 552 size_t initialOffset = this->addDraw(DRAW_IMAGE_LATTICE, &size); 553 this->addPaintPtr(paint); 554 this->addImage(image); 555 this->addInt(lattice.fXCount); 556 fWriter.writePad(lattice.fXDivs, lattice.fXCount * kUInt32Size); 557 this->addInt(lattice.fYCount); 558 fWriter.writePad(lattice.fYDivs, lattice.fYCount * kUInt32Size); 559 this->addInt(flagCount); 560 fWriter.writePad(lattice.fFlags, flagCount * sizeof(SkCanvas::Lattice::Flags)); 561 SkASSERT(lattice.fBounds); 562 this->addIRect(*lattice.fBounds); 563 this->addRect(dst); 564 this->validate(initialOffset, size); 565 } 566 567 void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 568 const SkPaint& paint) { 569 // op + paint index + length + 'length' worth of chars + x + y 570 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar); 571 572 DrawType op = DRAW_TEXT; 573 size_t initialOffset = this->addDraw(op, &size); 574 this->addPaint(paint); 575 this->addText(text, byteLength); 576 this->addScalar(x); 577 this->addScalar(y); 578 this->validate(initialOffset, size); 579 } 580 581 void SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], 582 const SkPaint& paint) { 583 int points = paint.countText(text, byteLength); 584 585 // op + paint index + length + 'length' worth of data + num points + x&y point data 586 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint); 587 588 DrawType op = DRAW_POS_TEXT; 589 590 size_t initialOffset = this->addDraw(op, &size); 591 this->addPaint(paint); 592 this->addText(text, byteLength); 593 this->addInt(points); 594 fWriter.writeMul4(pos, points * sizeof(SkPoint)); 595 this->validate(initialOffset, size); 596 } 597 598 void SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 599 SkScalar constY, const SkPaint& paint) { 600 int points = paint.countText(text, byteLength); 601 602 // op + paint index + length + 'length' worth of data + num points 603 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size; 604 // + y + the actual points 605 size += 1 * kUInt32Size + points * sizeof(SkScalar); 606 607 size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size); 608 this->addPaint(paint); 609 this->addText(text, byteLength); 610 this->addInt(points); 611 this->addScalar(constY); 612 fWriter.writeMul4(xpos, points * sizeof(SkScalar)); 613 this->validate(initialOffset, size); 614 } 615 616 void SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 617 const SkMatrix* matrix, const SkPaint& paint) { 618 // op + paint index + length + 'length' worth of data + path index + matrix 619 const SkMatrix& m = matrix ? *matrix : SkMatrix::I(); 620 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(nullptr); 621 size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size); 622 this->addPaint(paint); 623 this->addText(text, byteLength); 624 this->addPath(path); 625 this->addMatrix(m); 626 this->validate(initialOffset, size); 627 } 628 629 void SkPictureRecord::onDrawTextRSXform(const void* text, size_t byteLength, 630 const SkRSXform xform[], const SkRect* cull, 631 const SkPaint& paint) { 632 const int count = paint.countText(text, byteLength); 633 // [op + paint-index + count + flags + length] + [text] + [xform] + cull 634 size_t size = 5 * kUInt32Size + SkAlign4(byteLength) + count * sizeof(SkRSXform); 635 uint32_t flags = 0; 636 if (cull) { 637 flags |= DRAW_TEXT_RSXFORM_HAS_CULL; 638 size += sizeof(SkRect); 639 } 640 641 size_t initialOffset = this->addDraw(DRAW_TEXT_RSXFORM, &size); 642 this->addPaint(paint); 643 this->addInt(count); 644 this->addInt(flags); 645 this->addText(text, byteLength); 646 fWriter.write(xform, count * sizeof(SkRSXform)); 647 if (cull) { 648 fWriter.write(cull, sizeof(SkRect)); 649 } 650 this->validate(initialOffset, size); 651 } 652 653 void SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 654 const SkPaint& paint) { 655 656 // op + paint index + blob index + x/y 657 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar); 658 size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size); 659 660 this->addPaint(paint); 661 this->addTextBlob(blob); 662 this->addScalar(x); 663 this->addScalar(y); 664 665 this->validate(initialOffset, size); 666 } 667 668 void SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, 669 const SkPaint* paint) { 670 // op + picture index 671 size_t size = 2 * kUInt32Size; 672 size_t initialOffset; 673 674 if (nullptr == matrix && nullptr == paint) { 675 initialOffset = this->addDraw(DRAW_PICTURE, &size); 676 this->addPicture(picture); 677 } else { 678 const SkMatrix& m = matrix ? *matrix : SkMatrix::I(); 679 size += m.writeToMemory(nullptr) + kUInt32Size; // matrix + paint 680 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size); 681 this->addPaintPtr(paint); 682 this->addMatrix(m); 683 this->addPicture(picture); 684 } 685 this->validate(initialOffset, size); 686 } 687 688 void SkPictureRecord::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) { 689 // op + drawable index 690 size_t size = 2 * kUInt32Size; 691 size_t initialOffset; 692 693 if (nullptr == matrix) { 694 initialOffset = this->addDraw(DRAW_DRAWABLE, &size); 695 this->addDrawable(drawable); 696 } else { 697 size += matrix->writeToMemory(nullptr); // matrix 698 initialOffset = this->addDraw(DRAW_DRAWABLE_MATRIX, &size); 699 this->addMatrix(*matrix); 700 this->addDrawable(drawable); 701 } 702 this->validate(initialOffset, size); 703 } 704 705 void SkPictureRecord::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode mode, 706 const SkPaint& paint) { 707 // op + paint index + vertices index + mode 708 size_t size = 4 * kUInt32Size; 709 size_t initialOffset = this->addDraw(DRAW_VERTICES_OBJECT, &size); 710 711 this->addPaint(paint); 712 this->addVertices(vertices); 713 this->addInt(static_cast<uint32_t>(mode)); 714 715 this->validate(initialOffset, size); 716 } 717 718 void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], 719 const SkPoint texCoords[4], SkBlendMode bmode, 720 const SkPaint& paint) { 721 // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates 722 size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size; 723 uint32_t flag = 0; 724 if (colors) { 725 flag |= DRAW_VERTICES_HAS_COLORS; 726 size += SkPatchUtils::kNumCorners * sizeof(SkColor); 727 } 728 if (texCoords) { 729 flag |= DRAW_VERTICES_HAS_TEXS; 730 size += SkPatchUtils::kNumCorners * sizeof(SkPoint); 731 } 732 if (SkBlendMode::kModulate != bmode) { 733 flag |= DRAW_VERTICES_HAS_XFER; 734 size += kUInt32Size; 735 } 736 737 size_t initialOffset = this->addDraw(DRAW_PATCH, &size); 738 this->addPaint(paint); 739 this->addPatch(cubics); 740 this->addInt(flag); 741 742 // write optional parameters 743 if (colors) { 744 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor)); 745 } 746 if (texCoords) { 747 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint)); 748 } 749 if (flag & DRAW_VERTICES_HAS_XFER) { 750 this->addInt((int)bmode); 751 } 752 this->validate(initialOffset, size); 753 } 754 755 void SkPictureRecord::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], 756 const SkColor colors[], int count, SkBlendMode mode, 757 const SkRect* cull, const SkPaint* paint) { 758 // [op + paint-index + atlas-index + flags + count] + [xform] + [tex] + [*colors + mode] + cull 759 size_t size = 5 * kUInt32Size + count * sizeof(SkRSXform) + count * sizeof(SkRect); 760 uint32_t flags = 0; 761 if (colors) { 762 flags |= DRAW_ATLAS_HAS_COLORS; 763 size += count * sizeof(SkColor); 764 size += sizeof(uint32_t); // xfermode::mode 765 } 766 if (cull) { 767 flags |= DRAW_ATLAS_HAS_CULL; 768 size += sizeof(SkRect); 769 } 770 771 size_t initialOffset = this->addDraw(DRAW_ATLAS, &size); 772 this->addPaintPtr(paint); 773 this->addImage(atlas); 774 this->addInt(flags); 775 this->addInt(count); 776 fWriter.write(xform, count * sizeof(SkRSXform)); 777 fWriter.write(tex, count * sizeof(SkRect)); 778 779 // write optional parameters 780 if (colors) { 781 fWriter.write(colors, count * sizeof(SkColor)); 782 this->addInt((int)mode); 783 } 784 if (cull) { 785 fWriter.write(cull, sizeof(SkRect)); 786 } 787 this->validate(initialOffset, size); 788 } 789 790 void SkPictureRecord::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) { 791 // op + path index + zParams + lightPos + lightRadius + spot/ambient alphas + color + flags 792 size_t size = 2 * kUInt32Size + 2 * sizeof(SkPoint3) + 3 * sizeof(SkScalar) + 2 * kUInt32Size; 793 size_t initialOffset = this->addDraw(DRAW_SHADOW_REC, &size); 794 795 this->addPath(path); 796 797 fWriter.writePoint3(rec.fZPlaneParams); 798 fWriter.writePoint3(rec.fLightPos); 799 fWriter.writeScalar(rec.fLightRadius); 800 fWriter.writeScalar(rec.fAmbientAlpha); 801 fWriter.writeScalar(rec.fSpotAlpha); 802 fWriter.write32(rec.fColor); 803 fWriter.write32(rec.fFlags); 804 805 this->validate(initialOffset, size); 806 } 807 808 void SkPictureRecord::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) { 809 size_t keyLen = fWriter.WriteStringSize(key); 810 size_t valueLen = fWriter.WriteDataSize(value); 811 size_t size = 4 + sizeof(SkRect) + keyLen + valueLen; 812 813 size_t initialOffset = this->addDraw(DRAW_ANNOTATION, &size); 814 this->addRect(rect); 815 fWriter.writeString(key); 816 fWriter.writeData(value); 817 this->validate(initialOffset, size); 818 } 819 820 /////////////////////////////////////////////////////////////////////////////// 821 822 template <typename T> int find_or_append_uniqueID(SkTDArray<const T*>& array, const T* obj) { 823 int index = array.select([&](const T* elem) { 824 return elem->uniqueID() == obj->uniqueID(); 825 }); 826 if (index < 0) { 827 index = array.count(); 828 *array.append() = SkRef(obj); 829 } 830 return index; 831 } 832 833 sk_sp<SkSurface> SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) { 834 return nullptr; 835 } 836 837 void SkPictureRecord::addImage(const SkImage* image) { 838 // convention for images is 0-based index 839 this->addInt(find_or_append_uniqueID(fImageRefs, image)); 840 } 841 842 void SkPictureRecord::addMatrix(const SkMatrix& matrix) { 843 fWriter.writeMatrix(matrix); 844 } 845 846 void SkPictureRecord::addPaintPtr(const SkPaint* paint) { 847 fContentInfo.onAddPaintPtr(paint); 848 849 if (paint) { 850 fPaints.push_back(*paint); 851 this->addInt(fPaints.count()); 852 } else { 853 this->addInt(0); 854 } 855 } 856 857 int SkPictureRecord::addPathToHeap(const SkPath& path) { 858 if (int* n = fPaths.find(path)) { 859 return *n; 860 } 861 int n = fPaths.count() + 1; // 0 is reserved for null / error. 862 fPaths.set(path, n); 863 return n; 864 } 865 866 void SkPictureRecord::addPath(const SkPath& path) { 867 this->addInt(this->addPathToHeap(path)); 868 } 869 870 void SkPictureRecord::addPatch(const SkPoint cubics[12]) { 871 fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint)); 872 } 873 874 void SkPictureRecord::addPicture(const SkPicture* picture) { 875 // follow the convention of recording a 1-based index 876 this->addInt(find_or_append_uniqueID(fPictureRefs, picture) + 1); 877 } 878 879 void SkPictureRecord::addDrawable(SkDrawable* drawable) { 880 int index = fDrawableRefs.find(drawable); 881 if (index < 0) { // not found 882 index = fDrawableRefs.count(); 883 *fDrawableRefs.append() = drawable; 884 drawable->ref(); 885 } 886 // follow the convention of recording a 1-based index 887 this->addInt(index + 1); 888 } 889 890 void SkPictureRecord::addPoint(const SkPoint& point) { 891 fWriter.writePoint(point); 892 } 893 894 void SkPictureRecord::addPoints(const SkPoint pts[], int count) { 895 fWriter.writeMul4(pts, count * sizeof(SkPoint)); 896 } 897 898 void SkPictureRecord::addNoOp() { 899 size_t size = kUInt32Size; // op 900 this->addDraw(NOOP, &size); 901 } 902 903 void SkPictureRecord::addRect(const SkRect& rect) { 904 fWriter.writeRect(rect); 905 } 906 907 void SkPictureRecord::addRectPtr(const SkRect* rect) { 908 if (fWriter.writeBool(rect != nullptr)) { 909 fWriter.writeRect(*rect); 910 } 911 } 912 913 void SkPictureRecord::addIRect(const SkIRect& rect) { 914 fWriter.write(&rect, sizeof(rect)); 915 } 916 917 void SkPictureRecord::addIRectPtr(const SkIRect* rect) { 918 if (fWriter.writeBool(rect != nullptr)) { 919 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect; 920 } 921 } 922 923 void SkPictureRecord::addRRect(const SkRRect& rrect) { 924 fWriter.writeRRect(rrect); 925 } 926 927 void SkPictureRecord::addRegion(const SkRegion& region) { 928 fWriter.writeRegion(region); 929 } 930 931 void SkPictureRecord::addText(const void* text, size_t byteLength) { 932 fContentInfo.onDrawText(); 933 addInt(SkToInt(byteLength)); 934 fWriter.writePad(text, byteLength); 935 } 936 937 void SkPictureRecord::addTextBlob(const SkTextBlob* blob) { 938 // follow the convention of recording a 1-based index 939 this->addInt(find_or_append_uniqueID(fTextBlobRefs, blob) + 1); 940 } 941 942 void SkPictureRecord::addVertices(const SkVertices* vertices) { 943 // follow the convention of recording a 1-based index 944 this->addInt(find_or_append_uniqueID(fVerticesRefs, vertices) + 1); 945 } 946 947 /////////////////////////////////////////////////////////////////////////////// 948