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