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