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