1 2 /* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 #include "SkPictureRecord.h" 9 #include "SkTSearch.h" 10 #include "SkPixelRef.h" 11 #include "SkRRect.h" 12 #include "SkBBoxHierarchy.h" 13 #include "SkPictureStateTree.h" 14 15 #define MIN_WRITER_SIZE 16384 16 #define HEAP_BLOCK_SIZE 4096 17 18 enum { 19 // just need a value that save or getSaveCount would never return 20 kNoInitialSave = -1, 21 }; 22 23 SkPictureRecord::SkPictureRecord(uint32_t flags, SkDevice* device) : 24 INHERITED(device), 25 fBoundingHierarchy(NULL), 26 fStateTree(NULL), 27 fFlattenableHeap(HEAP_BLOCK_SIZE), 28 fMatrices(&fFlattenableHeap), 29 fPaints(&fFlattenableHeap), 30 fRegions(&fFlattenableHeap), 31 fWriter(MIN_WRITER_SIZE), 32 fRecordFlags(flags) { 33 #ifdef SK_DEBUG_SIZE 34 fPointBytes = fRectBytes = fTextBytes = 0; 35 fPointWrites = fRectWrites = fTextWrites = 0; 36 #endif 37 38 fRestoreOffsetStack.setReserve(32); 39 40 fBitmapHeap = SkNEW(SkBitmapHeap); 41 fFlattenableHeap.setBitmapStorage(fBitmapHeap); 42 fPathHeap = NULL; // lazy allocate 43 fFirstSavedLayerIndex = kNoSavedLayerIndex; 44 45 fInitialSaveCount = kNoInitialSave; 46 } 47 48 SkPictureRecord::~SkPictureRecord() { 49 SkSafeUnref(fBitmapHeap); 50 SkSafeUnref(fPathHeap); 51 SkSafeUnref(fBoundingHierarchy); 52 SkSafeUnref(fStateTree); 53 fFlattenableHeap.setBitmapStorage(NULL); 54 fPictureRefs.unrefAll(); 55 } 56 57 /////////////////////////////////////////////////////////////////////////////// 58 59 SkDevice* SkPictureRecord::setDevice(SkDevice* device) { 60 SkASSERT(!"eeek, don't try to change the device on a recording canvas"); 61 return this->INHERITED::setDevice(device); 62 } 63 64 int SkPictureRecord::save(SaveFlags flags) { 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.size()); 68 69 addDraw(SAVE); 70 addInt(flags); 71 72 validate(); 73 return this->INHERITED::save(flags); 74 } 75 76 int SkPictureRecord::saveLayer(const SkRect* bounds, const SkPaint* paint, 77 SaveFlags flags) { 78 // record the offset to us, making it non-positive to distinguish a save 79 // from a clip entry. 80 fRestoreOffsetStack.push(-(int32_t)fWriter.size()); 81 82 addDraw(SAVE_LAYER); 83 addRectPtr(bounds); 84 addPaintPtr(paint); 85 addInt(flags); 86 87 if (kNoSavedLayerIndex == fFirstSavedLayerIndex) { 88 fFirstSavedLayerIndex = fRestoreOffsetStack.count(); 89 } 90 91 validate(); 92 /* Don't actually call saveLayer, because that will try to allocate an 93 offscreen device (potentially very big) which we don't actually need 94 at this time (and may not be able to afford since during record our 95 clip starts out the size of the picture, which is often much larger 96 than the size of the actual device we'll use during playback). 97 */ 98 int count = this->INHERITED::save(flags); 99 this->clipRectBounds(bounds, flags, NULL); 100 return count; 101 } 102 103 bool SkPictureRecord::isDrawingToLayer() const { 104 return fFirstSavedLayerIndex != kNoSavedLayerIndex; 105 } 106 107 // Return the size of the specified drawType's recorded block, or 0 if this verb 108 // is variable sized, and therefore not known. 109 static inline uint32_t getSkipableSize(unsigned drawType) { 110 static const uint8_t gSizes[LAST_DRAWTYPE_ENUM + 1] = { 111 0, // UNUSED, 112 4, // CLIP_PATH, 113 4, // CLIP_REGION, 114 7, // CLIP_RECT, 115 15, // CLIP_RRECT, 116 2, // CONCAT, 117 0, // DRAW_BITMAP, 118 0, // DRAW_BITMAP_MATRIX, 119 0, // DRAW_BITMAP_NINE, 120 0, // DRAW_BITMAP_RECT, 121 0, // DRAW_CLEAR, 122 0, // DRAW_DATA, 123 0, // DRAW_OVAL, 124 0, // DRAW_PAINT, 125 0, // DRAW_PATH, 126 0, // DRAW_PICTURE, 127 0, // DRAW_POINTS, 128 0, // DRAW_POS_TEXT, 129 0, // DRAW_POS_TEXT_TOP_BOTTOM, // fast variant of DRAW_POS_TEXT 130 0, // DRAW_POS_TEXT_H, 131 0, // DRAW_POS_TEXT_H_TOP_BOTTOM, // fast variant of DRAW_POS_TEXT_H 132 0, // DRAW_RECT, 133 0, // DRAW_RRECT, 134 0, // DRAW_SPRITE, 135 0, // DRAW_TEXT, 136 0, // DRAW_TEXT_ON_PATH, 137 0, // DRAW_TEXT_TOP_BOTTOM, // fast variant of DRAW_TEXT 138 0, // DRAW_VERTICES, 139 0, // RESTORE, 140 2, // ROTATE, 141 2, // SAVE, 142 0, // SAVE_LAYER, 143 3, // SCALE, 144 2, // SET_MATRIX, 145 3, // SKEW, 146 3, // TRANSLATE, 147 }; 148 149 SkASSERT(sizeof(gSizes) == LAST_DRAWTYPE_ENUM + 1); 150 SkASSERT((unsigned)drawType <= (unsigned)LAST_DRAWTYPE_ENUM); 151 return gSizes[drawType] * sizeof(uint32_t); 152 } 153 154 #ifdef TRACK_COLLAPSE_STATS 155 static int gCollapseCount, gCollapseCalls; 156 #endif 157 158 /* 159 * Restore has just been called (but not recoreded), so look back at the 160 * matching save(), and see if we can eliminate the pair of them, due to no 161 * intervening matrix/clip calls. 162 * 163 * If so, update the writer and return true, in which case we won't even record 164 * the restore() call. If we still need the restore(), return false. 165 */ 166 static bool collapseSaveClipRestore(SkWriter32* writer, int32_t offset) { 167 #ifdef TRACK_COLLAPSE_STATS 168 gCollapseCalls += 1; 169 #endif 170 171 int32_t restoreOffset = (int32_t)writer->size(); 172 173 // back up to the save block 174 while (offset > 0) { 175 offset = *writer->peek32(offset); 176 } 177 178 // now offset points to a save 179 offset = -offset; 180 if (SAVE_LAYER == *writer->peek32(offset)) { 181 // not ready to cull these out yet (mrr) 182 return false; 183 } 184 SkASSERT(SAVE == *writer->peek32(offset)); 185 186 // Walk forward until we get back to either a draw-verb (abort) or we hit 187 // our restore (success). 188 int32_t saveOffset = offset; 189 190 offset += getSkipableSize(SAVE); 191 while (offset < restoreOffset) { 192 uint32_t* block = writer->peek32(offset); 193 uint32_t op = *block; 194 uint32_t opSize = getSkipableSize(op); 195 if (0 == opSize) { 196 // drawing verb, abort 197 return false; 198 } 199 offset += opSize; 200 } 201 202 #ifdef TRACK_COLLAPSE_STATS 203 gCollapseCount += 1; 204 SkDebugf("Collapse [%d out of %d] %g%spn", gCollapseCount, gCollapseCalls, 205 (double)gCollapseCount / gCollapseCalls, "%"); 206 #endif 207 208 writer->rewindToOffset(saveOffset); 209 return true; 210 } 211 212 void SkPictureRecord::restore() { 213 // FIXME: SkDeferredCanvas needs to be refactored to respect 214 // save/restore balancing so that the following test can be 215 // turned on permanently. 216 #if 0 217 SkASSERT(fRestoreOffsetStack.count() > 1); 218 #endif 219 220 // check for underflow 221 if (fRestoreOffsetStack.count() == 0) { 222 return; 223 } 224 225 if (fRestoreOffsetStack.count() == fFirstSavedLayerIndex) { 226 fFirstSavedLayerIndex = kNoSavedLayerIndex; 227 } 228 229 if (!collapseSaveClipRestore(&fWriter, fRestoreOffsetStack.top())) { 230 fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.size()); 231 this->addDraw(RESTORE); 232 } 233 234 fRestoreOffsetStack.pop(); 235 236 validate(); 237 return this->INHERITED::restore(); 238 } 239 240 bool SkPictureRecord::translate(SkScalar dx, SkScalar dy) { 241 addDraw(TRANSLATE); 242 addScalar(dx); 243 addScalar(dy); 244 validate(); 245 return this->INHERITED::translate(dx, dy); 246 } 247 248 bool SkPictureRecord::scale(SkScalar sx, SkScalar sy) { 249 addDraw(SCALE); 250 addScalar(sx); 251 addScalar(sy); 252 validate(); 253 return this->INHERITED::scale(sx, sy); 254 } 255 256 bool SkPictureRecord::rotate(SkScalar degrees) { 257 addDraw(ROTATE); 258 addScalar(degrees); 259 validate(); 260 return this->INHERITED::rotate(degrees); 261 } 262 263 bool SkPictureRecord::skew(SkScalar sx, SkScalar sy) { 264 addDraw(SKEW); 265 addScalar(sx); 266 addScalar(sy); 267 validate(); 268 return this->INHERITED::skew(sx, sy); 269 } 270 271 bool SkPictureRecord::concat(const SkMatrix& matrix) { 272 validate(); 273 addDraw(CONCAT); 274 addMatrix(matrix); 275 validate(); 276 return this->INHERITED::concat(matrix); 277 } 278 279 void SkPictureRecord::setMatrix(const SkMatrix& matrix) { 280 validate(); 281 addDraw(SET_MATRIX); 282 addMatrix(matrix); 283 validate(); 284 this->INHERITED::setMatrix(matrix); 285 } 286 287 static bool regionOpExpands(SkRegion::Op op) { 288 switch (op) { 289 case SkRegion::kUnion_Op: 290 case SkRegion::kXOR_Op: 291 case SkRegion::kReverseDifference_Op: 292 case SkRegion::kReplace_Op: 293 return true; 294 case SkRegion::kIntersect_Op: 295 case SkRegion::kDifference_Op: 296 return false; 297 default: 298 SkDEBUGFAIL("unknown region op"); 299 return false; 300 } 301 } 302 303 void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel( 304 uint32_t restoreOffset) { 305 int32_t offset = fRestoreOffsetStack.top(); 306 while (offset > 0) { 307 uint32_t* peek = fWriter.peek32(offset); 308 offset = *peek; 309 *peek = restoreOffset; 310 } 311 312 #ifdef SK_DEBUG 313 // assert that the final offset value points to a save verb 314 uint32_t drawOp = *fWriter.peek32(-offset); 315 SkASSERT(SAVE == drawOp || SAVE_LAYER == drawOp); 316 #endif 317 } 318 319 void SkPictureRecord::beginRecording() { 320 // we have to call this *after* our constructor, to ensure that it gets 321 // recorded. This is balanced by restoreToCount() call from endRecording, 322 // which in-turn calls our overridden restore(), so those get recorded too. 323 fInitialSaveCount = this->save(kMatrixClip_SaveFlag); 324 } 325 326 void SkPictureRecord::endRecording() { 327 SkASSERT(kNoInitialSave != fInitialSaveCount); 328 this->restoreToCount(fInitialSaveCount); 329 } 330 331 void SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) { 332 if (fRestoreOffsetStack.isEmpty()) { 333 return; 334 } 335 336 if (regionOpExpands(op)) { 337 // Run back through any previous clip ops, and mark their offset to 338 // be 0, disabling their ability to trigger a jump-to-restore, otherwise 339 // they could hide this clips ability to expand the clip (i.e. go from 340 // empty to non-empty). 341 fillRestoreOffsetPlaceholdersForCurrentStackLevel(0); 342 } 343 344 size_t offset = fWriter.size(); 345 // The RestoreOffset field is initially filled with a placeholder 346 // value that points to the offset of the previous RestoreOffset 347 // in the current stack level, thus forming a linked list so that 348 // the restore offsets can be filled in when the corresponding 349 // restore command is recorded. 350 addInt(fRestoreOffsetStack.top()); 351 fRestoreOffsetStack.top() = offset; 352 } 353 354 bool SkPictureRecord::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { 355 addDraw(CLIP_RECT); 356 addRect(rect); 357 addInt(ClipParams_pack(op, doAA)); 358 recordRestoreOffsetPlaceholder(op); 359 360 validate(); 361 return this->INHERITED::clipRect(rect, op, doAA); 362 } 363 364 bool SkPictureRecord::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) { 365 if (rrect.isRect()) { 366 return this->SkPictureRecord::clipRect(rrect.getBounds(), op, doAA); 367 } 368 369 addDraw(CLIP_RRECT); 370 addRRect(rrect); 371 addInt(ClipParams_pack(op, doAA)); 372 recordRestoreOffsetPlaceholder(op); 373 374 validate(); 375 376 if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) { 377 return this->INHERITED::clipRect(rrect.getBounds(), op, doAA); 378 } else { 379 return this->INHERITED::clipRRect(rrect, op, doAA); 380 } 381 } 382 383 bool SkPictureRecord::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { 384 385 SkRect r; 386 if (!path.isInverseFillType() && path.isRect(&r)) { 387 return this->clipRect(r, op, doAA); 388 } 389 390 addDraw(CLIP_PATH); 391 addPath(path); 392 addInt(ClipParams_pack(op, doAA)); 393 recordRestoreOffsetPlaceholder(op); 394 395 validate(); 396 397 if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) { 398 return this->INHERITED::clipRect(path.getBounds(), op, doAA); 399 } else { 400 return this->INHERITED::clipPath(path, op, doAA); 401 } 402 } 403 404 bool SkPictureRecord::clipRegion(const SkRegion& region, SkRegion::Op op) { 405 addDraw(CLIP_REGION); 406 addRegion(region); 407 addInt(ClipParams_pack(op, false)); 408 recordRestoreOffsetPlaceholder(op); 409 410 validate(); 411 return this->INHERITED::clipRegion(region, op); 412 } 413 414 void SkPictureRecord::clear(SkColor color) { 415 addDraw(DRAW_CLEAR); 416 addInt(color); 417 validate(); 418 } 419 420 void SkPictureRecord::drawPaint(const SkPaint& paint) { 421 addDraw(DRAW_PAINT); 422 addPaint(paint); 423 validate(); 424 } 425 426 void SkPictureRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts[], 427 const SkPaint& paint) { 428 addDraw(DRAW_POINTS); 429 addPaint(paint); 430 addInt(mode); 431 addInt(count); 432 fWriter.writeMul4(pts, count * sizeof(SkPoint)); 433 validate(); 434 } 435 436 void SkPictureRecord::drawOval(const SkRect& oval, const SkPaint& paint) { 437 addDraw(DRAW_OVAL); 438 addPaint(paint); 439 addRect(oval); 440 validate(); 441 } 442 443 void SkPictureRecord::drawRect(const SkRect& rect, const SkPaint& paint) { 444 addDraw(DRAW_RECT); 445 addPaint(paint); 446 addRect(rect); 447 validate(); 448 } 449 450 void SkPictureRecord::drawRRect(const SkRRect& rrect, const SkPaint& paint) { 451 if (rrect.isRect()) { 452 addDraw(DRAW_RECT); 453 addPaint(paint); 454 addRect(rrect.getBounds()); 455 } else if (rrect.isOval()) { 456 addDraw(DRAW_OVAL); 457 addPaint(paint); 458 addRect(rrect.getBounds()); 459 } else { 460 addDraw(DRAW_RRECT); 461 addPaint(paint); 462 addRRect(rrect); 463 } 464 validate(); 465 } 466 467 void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) { 468 addDraw(DRAW_PATH); 469 addPaint(paint); 470 addPath(path); 471 validate(); 472 } 473 474 void SkPictureRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, 475 const SkPaint* paint = NULL) { 476 addDraw(DRAW_BITMAP); 477 addPaintPtr(paint); 478 addBitmap(bitmap); 479 addScalar(left); 480 addScalar(top); 481 validate(); 482 } 483 484 void SkPictureRecord::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, 485 const SkRect& dst, const SkPaint* paint) { 486 addDraw(DRAW_BITMAP_RECT_TO_RECT); 487 addPaintPtr(paint); 488 addBitmap(bitmap); 489 addRectPtr(src); // may be null 490 addRect(dst); 491 validate(); 492 } 493 494 void SkPictureRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix, 495 const SkPaint* paint) { 496 addDraw(DRAW_BITMAP_MATRIX); 497 addPaintPtr(paint); 498 addBitmap(bitmap); 499 addMatrix(matrix); 500 validate(); 501 } 502 503 void SkPictureRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, 504 const SkRect& dst, const SkPaint* paint) { 505 addDraw(DRAW_BITMAP_NINE); 506 addPaintPtr(paint); 507 addBitmap(bitmap); 508 addIRect(center); 509 addRect(dst); 510 validate(); 511 } 512 513 void SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top, 514 const SkPaint* paint = NULL) { 515 addDraw(DRAW_SPRITE); 516 addPaintPtr(paint); 517 addBitmap(bitmap); 518 addInt(left); 519 addInt(top); 520 validate(); 521 } 522 523 // Return fontmetrics.fTop,fBottom in topbot[0,1], after they have been 524 // tweaked by paint.computeFastBounds(). 525 // 526 static void computeFontMetricsTopBottom(const SkPaint& paint, SkScalar topbot[2]) { 527 SkPaint::FontMetrics metrics; 528 paint.getFontMetrics(&metrics); 529 SkRect bounds; 530 // construct a rect so we can see any adjustments from the paint. 531 // we use 0,1 for left,right, just so the rect isn't empty 532 bounds.set(0, metrics.fTop, SK_Scalar1, metrics.fBottom); 533 (void)paint.computeFastBounds(bounds, &bounds); 534 topbot[0] = bounds.fTop; 535 topbot[1] = bounds.fBottom; 536 } 537 538 void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint, const SkFlatData& flat, 539 SkScalar minY, SkScalar maxY) { 540 if (!flat.isTopBotWritten()) { 541 computeFontMetricsTopBottom(paint, flat.writableTopBot()); 542 SkASSERT(flat.isTopBotWritten()); 543 } 544 addScalar(flat.topBot()[0] + minY); 545 addScalar(flat.topBot()[1] + maxY); 546 } 547 548 void SkPictureRecord::drawText(const void* text, size_t byteLength, SkScalar x, 549 SkScalar y, const SkPaint& paint) { 550 bool fast = !paint.isVerticalText() && paint.canComputeFastBounds(); 551 552 addDraw(fast ? DRAW_TEXT_TOP_BOTTOM : DRAW_TEXT); 553 const SkFlatData* flatPaintData = addPaint(paint); 554 SkASSERT(flatPaintData); 555 addText(text, byteLength); 556 addScalar(x); 557 addScalar(y); 558 if (fast) { 559 addFontMetricsTopBottom(paint, *flatPaintData, y, y); 560 } 561 validate(); 562 } 563 564 void SkPictureRecord::drawPosText(const void* text, size_t byteLength, 565 const SkPoint pos[], const SkPaint& paint) { 566 size_t points = paint.countText(text, byteLength); 567 if (0 == points) 568 return; 569 570 bool canUseDrawH = true; 571 SkScalar minY = pos[0].fY; 572 SkScalar maxY = pos[0].fY; 573 // check if the caller really should have used drawPosTextH() 574 { 575 const SkScalar firstY = pos[0].fY; 576 for (size_t index = 1; index < points; index++) { 577 if (pos[index].fY != firstY) { 578 canUseDrawH = false; 579 if (pos[index].fY < minY) { 580 minY = pos[index].fY; 581 } else if (pos[index].fY > maxY) { 582 maxY = pos[index].fY; 583 } 584 } 585 } 586 } 587 588 bool fastBounds = !paint.isVerticalText() && paint.canComputeFastBounds(); 589 bool fast = canUseDrawH && fastBounds; 590 591 if (fast) { 592 addDraw(DRAW_POS_TEXT_H_TOP_BOTTOM); 593 } else if (canUseDrawH) { 594 addDraw(DRAW_POS_TEXT_H); 595 } else if (fastBounds) { 596 addDraw(DRAW_POS_TEXT_TOP_BOTTOM); 597 } else { 598 addDraw(DRAW_POS_TEXT); 599 } 600 const SkFlatData* flatPaintData = addPaint(paint); 601 SkASSERT(flatPaintData); 602 addText(text, byteLength); 603 addInt(points); 604 605 #ifdef SK_DEBUG_SIZE 606 size_t start = fWriter.size(); 607 #endif 608 if (canUseDrawH) { 609 if (fast) { 610 addFontMetricsTopBottom(paint, *flatPaintData, pos[0].fY, pos[0].fY); 611 } 612 addScalar(pos[0].fY); 613 SkScalar* xptr = (SkScalar*)fWriter.reserve(points * sizeof(SkScalar)); 614 for (size_t index = 0; index < points; index++) 615 *xptr++ = pos[index].fX; 616 } 617 else { 618 fWriter.writeMul4(pos, points * sizeof(SkPoint)); 619 if (fastBounds) { 620 addFontMetricsTopBottom(paint, *flatPaintData, minY, maxY); 621 } 622 } 623 #ifdef SK_DEBUG_SIZE 624 fPointBytes += fWriter.size() - start; 625 fPointWrites += points; 626 #endif 627 validate(); 628 } 629 630 void SkPictureRecord::drawPosTextH(const void* text, size_t byteLength, 631 const SkScalar xpos[], SkScalar constY, 632 const SkPaint& paint) { 633 size_t points = paint.countText(text, byteLength); 634 if (0 == points) 635 return; 636 637 bool fast = !paint.isVerticalText() && paint.canComputeFastBounds(); 638 639 addDraw(fast ? DRAW_POS_TEXT_H_TOP_BOTTOM : DRAW_POS_TEXT_H); 640 const SkFlatData* flatPaintData = addPaint(paint); 641 SkASSERT(flatPaintData); 642 addText(text, byteLength); 643 addInt(points); 644 645 #ifdef SK_DEBUG_SIZE 646 size_t start = fWriter.size(); 647 #endif 648 if (fast) { 649 addFontMetricsTopBottom(paint, *flatPaintData, constY, constY); 650 } 651 addScalar(constY); 652 fWriter.writeMul4(xpos, points * sizeof(SkScalar)); 653 #ifdef SK_DEBUG_SIZE 654 fPointBytes += fWriter.size() - start; 655 fPointWrites += points; 656 #endif 657 validate(); 658 } 659 660 void SkPictureRecord::drawTextOnPath(const void* text, size_t byteLength, 661 const SkPath& path, const SkMatrix* matrix, 662 const SkPaint& paint) { 663 addDraw(DRAW_TEXT_ON_PATH); 664 addPaint(paint); 665 addText(text, byteLength); 666 addPath(path); 667 addMatrixPtr(matrix); 668 validate(); 669 } 670 671 void SkPictureRecord::drawPicture(SkPicture& picture) { 672 addDraw(DRAW_PICTURE); 673 addPicture(picture); 674 validate(); 675 } 676 677 void SkPictureRecord::drawVertices(VertexMode vmode, int vertexCount, 678 const SkPoint vertices[], const SkPoint texs[], 679 const SkColor colors[], SkXfermode*, 680 const uint16_t indices[], int indexCount, 681 const SkPaint& paint) { 682 uint32_t flags = 0; 683 if (texs) { 684 flags |= DRAW_VERTICES_HAS_TEXS; 685 } 686 if (colors) { 687 flags |= DRAW_VERTICES_HAS_COLORS; 688 } 689 if (indexCount > 0) { 690 flags |= DRAW_VERTICES_HAS_INDICES; 691 } 692 693 addDraw(DRAW_VERTICES); 694 addPaint(paint); 695 addInt(flags); 696 addInt(vmode); 697 addInt(vertexCount); 698 addPoints(vertices, vertexCount); 699 if (flags & DRAW_VERTICES_HAS_TEXS) { 700 addPoints(texs, vertexCount); 701 } 702 if (flags & DRAW_VERTICES_HAS_COLORS) { 703 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor)); 704 } 705 if (flags & DRAW_VERTICES_HAS_INDICES) { 706 addInt(indexCount); 707 fWriter.writePad(indices, indexCount * sizeof(uint16_t)); 708 } 709 } 710 711 void SkPictureRecord::drawData(const void* data, size_t length) { 712 addDraw(DRAW_DATA); 713 addInt(length); 714 fWriter.writePad(data, length); 715 } 716 717 /////////////////////////////////////////////////////////////////////////////// 718 719 void SkPictureRecord::addBitmap(const SkBitmap& bitmap) { 720 const int index = fBitmapHeap->insert(bitmap); 721 // In debug builds, a bad return value from insert() will crash, allowing for debugging. In 722 // release builds, the invalid value will be recorded so that the reader will know that there 723 // was a problem. 724 SkASSERT(index != SkBitmapHeap::INVALID_SLOT); 725 addInt(index); 726 } 727 728 void SkPictureRecord::addMatrix(const SkMatrix& matrix) { 729 addMatrixPtr(&matrix); 730 } 731 732 void SkPictureRecord::addMatrixPtr(const SkMatrix* matrix) { 733 this->addInt(matrix ? fMatrices.find(*matrix) : 0); 734 } 735 736 const SkFlatData* SkPictureRecord::addPaintPtr(const SkPaint* paint) { 737 const SkFlatData* data = paint ? fPaints.findAndReturnFlat(*paint) : NULL; 738 int index = data ? data->index() : 0; 739 this->addInt(index); 740 return data; 741 } 742 743 void SkPictureRecord::addPath(const SkPath& path) { 744 if (NULL == fPathHeap) { 745 fPathHeap = SkNEW(SkPathHeap); 746 } 747 addInt(fPathHeap->append(path)); 748 } 749 750 void SkPictureRecord::addPicture(SkPicture& picture) { 751 int index = fPictureRefs.find(&picture); 752 if (index < 0) { // not found 753 index = fPictureRefs.count(); 754 *fPictureRefs.append() = &picture; 755 picture.ref(); 756 } 757 // follow the convention of recording a 1-based index 758 addInt(index + 1); 759 } 760 761 void SkPictureRecord::addPoint(const SkPoint& point) { 762 #ifdef SK_DEBUG_SIZE 763 size_t start = fWriter.size(); 764 #endif 765 fWriter.writePoint(point); 766 #ifdef SK_DEBUG_SIZE 767 fPointBytes += fWriter.size() - start; 768 fPointWrites++; 769 #endif 770 } 771 772 void SkPictureRecord::addPoints(const SkPoint pts[], int count) { 773 fWriter.writeMul4(pts, count * sizeof(SkPoint)); 774 #ifdef SK_DEBUG_SIZE 775 fPointBytes += count * sizeof(SkPoint); 776 fPointWrites++; 777 #endif 778 } 779 780 void SkPictureRecord::addRect(const SkRect& rect) { 781 #ifdef SK_DEBUG_SIZE 782 size_t start = fWriter.size(); 783 #endif 784 fWriter.writeRect(rect); 785 #ifdef SK_DEBUG_SIZE 786 fRectBytes += fWriter.size() - start; 787 fRectWrites++; 788 #endif 789 } 790 791 void SkPictureRecord::addRectPtr(const SkRect* rect) { 792 if (fWriter.writeBool(rect != NULL)) { 793 fWriter.writeRect(*rect); 794 } 795 } 796 797 void SkPictureRecord::addIRect(const SkIRect& rect) { 798 fWriter.write(&rect, sizeof(rect)); 799 } 800 801 void SkPictureRecord::addIRectPtr(const SkIRect* rect) { 802 if (fWriter.writeBool(rect != NULL)) { 803 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect; 804 } 805 } 806 807 void SkPictureRecord::addRRect(const SkRRect& rrect) { 808 fWriter.writeRRect(rrect); 809 } 810 811 void SkPictureRecord::addRegion(const SkRegion& region) { 812 addInt(fRegions.find(region)); 813 } 814 815 void SkPictureRecord::addText(const void* text, size_t byteLength) { 816 #ifdef SK_DEBUG_SIZE 817 size_t start = fWriter.size(); 818 #endif 819 addInt(byteLength); 820 fWriter.writePad(text, byteLength); 821 #ifdef SK_DEBUG_SIZE 822 fTextBytes += fWriter.size() - start; 823 fTextWrites++; 824 #endif 825 } 826 827 /////////////////////////////////////////////////////////////////////////////// 828 829 #ifdef SK_DEBUG_SIZE 830 size_t SkPictureRecord::size() const { 831 size_t result = 0; 832 size_t sizeData; 833 bitmaps(&sizeData); 834 result += sizeData; 835 matrices(&sizeData); 836 result += sizeData; 837 paints(&sizeData); 838 result += sizeData; 839 paths(&sizeData); 840 result += sizeData; 841 pictures(&sizeData); 842 result += sizeData; 843 regions(&sizeData); 844 result += sizeData; 845 result += streamlen(); 846 return result; 847 } 848 849 int SkPictureRecord::bitmaps(size_t* size) const { 850 size_t result = 0; 851 int count = fBitmaps.count(); 852 for (int index = 0; index < count; index++) 853 result += sizeof(fBitmaps[index]) + fBitmaps[index]->size(); 854 *size = result; 855 return count; 856 } 857 858 int SkPictureRecord::matrices(size_t* size) const { 859 int count = fMatrices.count(); 860 *size = sizeof(fMatrices[0]) * count; 861 return count; 862 } 863 864 int SkPictureRecord::paints(size_t* size) const { 865 size_t result = 0; 866 int count = fPaints.count(); 867 for (int index = 0; index < count; index++) 868 result += sizeof(fPaints[index]) + fPaints[index]->size(); 869 *size = result; 870 return count; 871 } 872 873 int SkPictureRecord::paths(size_t* size) const { 874 size_t result = 0; 875 int count = fPaths.count(); 876 for (int index = 0; index < count; index++) 877 result += sizeof(fPaths[index]) + fPaths[index]->size(); 878 *size = result; 879 return count; 880 } 881 882 int SkPictureRecord::regions(size_t* size) const { 883 size_t result = 0; 884 int count = fRegions.count(); 885 for (int index = 0; index < count; index++) 886 result += sizeof(fRegions[index]) + fRegions[index]->size(); 887 *size = result; 888 return count; 889 } 890 891 size_t SkPictureRecord::streamlen() const { 892 return fWriter.size(); 893 } 894 #endif 895 896 #ifdef SK_DEBUG_VALIDATE 897 void SkPictureRecord::validate() const { 898 validateBitmaps(); 899 validateMatrices(); 900 validatePaints(); 901 validatePaths(); 902 validatePictures(); 903 validateRegions(); 904 } 905 906 void SkPictureRecord::validateBitmaps() const { 907 int count = fBitmaps.count(); 908 SkASSERT((unsigned) count < 0x1000); 909 for (int index = 0; index < count; index++) { 910 const SkFlatBitmap* bitPtr = fBitmaps[index]; 911 SkASSERT(bitPtr); 912 bitPtr->validate(); 913 } 914 } 915 916 void SkPictureRecord::validateMatrices() const { 917 int count = fMatrices.count(); 918 SkASSERT((unsigned) count < 0x1000); 919 for (int index = 0; index < count; index++) { 920 const SkFlatMatrix* matrix = fMatrices[index]; 921 SkASSERT(matrix); 922 matrix->validate(); 923 } 924 } 925 926 void SkPictureRecord::validatePaints() const { 927 int count = fPaints.count(); 928 SkASSERT((unsigned) count < 0x1000); 929 for (int index = 0; index < count; index++) { 930 const SkFlatPaint* paint = fPaints[index]; 931 SkASSERT(paint); 932 // paint->validate(); 933 } 934 } 935 936 void SkPictureRecord::validatePaths() const { 937 int count = fPaths.count(); 938 SkASSERT((unsigned) count < 0x1000); 939 for (int index = 0; index < count; index++) { 940 const SkFlatPath* path = fPaths[index]; 941 SkASSERT(path); 942 path->validate(); 943 } 944 } 945 946 void SkPictureRecord::validateRegions() const { 947 int count = fRegions.count(); 948 SkASSERT((unsigned) count < 0x1000); 949 for (int index = 0; index < count; index++) { 950 const SkFlatRegion* region = fRegions[index]; 951 SkASSERT(region); 952 region->validate(); 953 } 954 } 955 #endif 956