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