SkPictureRecord.cpp revision 5f0add3ad6e1d6129307276c81ba6624f92ca112
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 addInt(fBitmapHeap->insert(bitmap)); 661} 662 663void SkPictureRecord::addMatrix(const SkMatrix& matrix) { 664 addMatrixPtr(&matrix); 665} 666 667void SkPictureRecord::addMatrixPtr(const SkMatrix* matrix) { 668 this->addInt(matrix ? fMatrices.find(*matrix) : 0); 669} 670 671void SkPictureRecord::addPaint(const SkPaint& paint) { 672 addPaintPtr(&paint); 673} 674 675void SkPictureRecord::addPaintPtr(const SkPaint* paint) { 676 this->addInt(paint ? fPaints.find(*paint) : 0); 677} 678 679void SkPictureRecord::addPath(const SkPath& path) { 680 if (NULL == fPathHeap) { 681 fPathHeap = SkNEW(SkPathHeap); 682 } 683 addInt(fPathHeap->append(path)); 684} 685 686void SkPictureRecord::addPicture(SkPicture& picture) { 687 int index = fPictureRefs.find(&picture); 688 if (index < 0) { // not found 689 index = fPictureRefs.count(); 690 *fPictureRefs.append() = &picture; 691 picture.ref(); 692 } 693 // follow the convention of recording a 1-based index 694 addInt(index + 1); 695} 696 697void SkPictureRecord::addPoint(const SkPoint& point) { 698#ifdef SK_DEBUG_SIZE 699 size_t start = fWriter.size(); 700#endif 701 fWriter.writePoint(point); 702#ifdef SK_DEBUG_SIZE 703 fPointBytes += fWriter.size() - start; 704 fPointWrites++; 705#endif 706} 707 708void SkPictureRecord::addPoints(const SkPoint pts[], int count) { 709 fWriter.writeMul4(pts, count * sizeof(SkPoint)); 710#ifdef SK_DEBUG_SIZE 711 fPointBytes += count * sizeof(SkPoint); 712 fPointWrites++; 713#endif 714} 715 716void SkPictureRecord::addRect(const SkRect& rect) { 717#ifdef SK_DEBUG_SIZE 718 size_t start = fWriter.size(); 719#endif 720 fWriter.writeRect(rect); 721#ifdef SK_DEBUG_SIZE 722 fRectBytes += fWriter.size() - start; 723 fRectWrites++; 724#endif 725} 726 727void SkPictureRecord::addRectPtr(const SkRect* rect) { 728 if (fWriter.writeBool(rect != NULL)) { 729 fWriter.writeRect(*rect); 730 } 731} 732 733void SkPictureRecord::addIRect(const SkIRect& rect) { 734 fWriter.write(&rect, sizeof(rect)); 735} 736 737void SkPictureRecord::addIRectPtr(const SkIRect* rect) { 738 if (fWriter.writeBool(rect != NULL)) { 739 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect; 740 } 741} 742 743void SkPictureRecord::addRegion(const SkRegion& region) { 744 addInt(fRegions.find(region)); 745} 746 747void SkPictureRecord::addText(const void* text, size_t byteLength) { 748#ifdef SK_DEBUG_SIZE 749 size_t start = fWriter.size(); 750#endif 751 addInt(byteLength); 752 fWriter.writePad(text, byteLength); 753#ifdef SK_DEBUG_SIZE 754 fTextBytes += fWriter.size() - start; 755 fTextWrites++; 756#endif 757} 758 759/////////////////////////////////////////////////////////////////////////////// 760 761#ifdef SK_DEBUG_SIZE 762size_t SkPictureRecord::size() const { 763 size_t result = 0; 764 size_t sizeData; 765 bitmaps(&sizeData); 766 result += sizeData; 767 matrices(&sizeData); 768 result += sizeData; 769 paints(&sizeData); 770 result += sizeData; 771 paths(&sizeData); 772 result += sizeData; 773 pictures(&sizeData); 774 result += sizeData; 775 regions(&sizeData); 776 result += sizeData; 777 result += streamlen(); 778 return result; 779} 780 781int SkPictureRecord::bitmaps(size_t* size) const { 782 size_t result = 0; 783 int count = fBitmaps.count(); 784 for (int index = 0; index < count; index++) 785 result += sizeof(fBitmaps[index]) + fBitmaps[index]->size(); 786 *size = result; 787 return count; 788} 789 790int SkPictureRecord::matrices(size_t* size) const { 791 int count = fMatrices.count(); 792 *size = sizeof(fMatrices[0]) * count; 793 return count; 794} 795 796int SkPictureRecord::paints(size_t* size) const { 797 size_t result = 0; 798 int count = fPaints.count(); 799 for (int index = 0; index < count; index++) 800 result += sizeof(fPaints[index]) + fPaints[index]->size(); 801 *size = result; 802 return count; 803} 804 805int SkPictureRecord::paths(size_t* size) const { 806 size_t result = 0; 807 int count = fPaths.count(); 808 for (int index = 0; index < count; index++) 809 result += sizeof(fPaths[index]) + fPaths[index]->size(); 810 *size = result; 811 return count; 812} 813 814int SkPictureRecord::regions(size_t* size) const { 815 size_t result = 0; 816 int count = fRegions.count(); 817 for (int index = 0; index < count; index++) 818 result += sizeof(fRegions[index]) + fRegions[index]->size(); 819 *size = result; 820 return count; 821} 822 823size_t SkPictureRecord::streamlen() const { 824 return fWriter.size(); 825} 826#endif 827 828#ifdef SK_DEBUG_VALIDATE 829void SkPictureRecord::validate() const { 830 validateBitmaps(); 831 validateMatrices(); 832 validatePaints(); 833 validatePaths(); 834 validatePictures(); 835 validateRegions(); 836} 837 838void SkPictureRecord::validateBitmaps() const { 839 int count = fBitmaps.count(); 840 SkASSERT((unsigned) count < 0x1000); 841 for (int index = 0; index < count; index++) { 842 const SkFlatBitmap* bitPtr = fBitmaps[index]; 843 SkASSERT(bitPtr); 844 bitPtr->validate(); 845 } 846} 847 848void SkPictureRecord::validateMatrices() const { 849 int count = fMatrices.count(); 850 SkASSERT((unsigned) count < 0x1000); 851 for (int index = 0; index < count; index++) { 852 const SkFlatMatrix* matrix = fMatrices[index]; 853 SkASSERT(matrix); 854 matrix->validate(); 855 } 856} 857 858void SkPictureRecord::validatePaints() const { 859 int count = fPaints.count(); 860 SkASSERT((unsigned) count < 0x1000); 861 for (int index = 0; index < count; index++) { 862 const SkFlatPaint* paint = fPaints[index]; 863 SkASSERT(paint); 864// paint->validate(); 865 } 866} 867 868void SkPictureRecord::validatePaths() const { 869 int count = fPaths.count(); 870 SkASSERT((unsigned) count < 0x1000); 871 for (int index = 0; index < count; index++) { 872 const SkFlatPath* path = fPaths[index]; 873 SkASSERT(path); 874 path->validate(); 875 } 876} 877 878void SkPictureRecord::validateRegions() const { 879 int count = fRegions.count(); 880 SkASSERT((unsigned) count < 0x1000); 881 for (int index = 0; index < count; index++) { 882 const SkFlatRegion* region = fRegions[index]; 883 SkASSERT(region); 884 region->validate(); 885 } 886} 887#endif 888 889