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