Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / core / SkPictureRecord.cpp
index 997b974..f6da2f2 100644 (file)
 #include "SkRRect.h"
 #include "SkBBoxHierarchy.h"
 #include "SkDevice.h"
-#include "SkOffsetTable.h"
 #include "SkPictureStateTree.h"
-#include "SkSurface.h"
 
 #define HEAP_BLOCK_SIZE 4096
 
+// If SK_RECORD_LITERAL_PICTURES is defined, record our inputs as literally as possible.
+// Otherwise, we can be clever and record faster equivalents.  kBeClever is normally true.
+static const bool kBeClever =
+#ifdef SK_RECORD_LITERAL_PICTURES
+    false;
+#else
+    true;
+#endif
+
 enum {
     // just need a value that save or getSaveCount would never return
     kNoInitialSave = -1,
@@ -29,22 +36,22 @@ static const uint32_t kSaveSize = 2 * kUInt32Size;
 static const uint32_t kSaveLayerNoBoundsSize = 4 * kUInt32Size;
 static const uint32_t kSaveLayerWithBoundsSize = 4 * kUInt32Size + sizeof(SkRect);
 
-SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
+SkPictureRecord::SkPictureRecord(SkPicture* picture, const SkISize& dimensions, uint32_t flags)
     : INHERITED(dimensions.width(), dimensions.height())
     , fBoundingHierarchy(NULL)
     , fStateTree(NULL)
     , fFlattenableHeap(HEAP_BLOCK_SIZE)
     , fPaints(&fFlattenableHeap)
     , fRecordFlags(flags)
-    , fOptsEnabled(true) {
+    , fOptsEnabled(kBeClever) {
 #ifdef SK_DEBUG_SIZE
     fPointBytes = fRectBytes = fTextBytes = 0;
     fPointWrites = fRectWrites = fTextWrites = 0;
 #endif
 
+    fPicture = picture;
     fBitmapHeap = SkNEW(SkBitmapHeap);
     fFlattenableHeap.setBitmapStorage(fBitmapHeap);
-    fPathHeap = NULL;   // lazy allocate
 
 #ifndef SK_COLLAPSE_MATRIX_CLIP_STATE
     fFirstSavedLayerIndex = kNoSavedLayerIndex;
@@ -59,7 +66,6 @@ SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
 
 SkPictureRecord::~SkPictureRecord() {
     SkSafeUnref(fBitmapHeap);
-    SkSafeUnref(fPathHeap);
     SkSafeUnref(fBoundingHierarchy);
     SkSafeUnref(fStateTree);
     fFlattenableHeap.setBitmapStorage(NULL);
@@ -71,7 +77,7 @@ SkPictureRecord::~SkPictureRecord() {
 // Return the offset of the paint inside a given op's byte stream. A zero
 // return value means there is no paint (and you really shouldn't be calling
 // this method)
-static inline uint32_t getPaintOffset(DrawType op, uint32_t opSize) {
+static inline size_t getPaintOffset(DrawType op, size_t opSize) {
     // These offsets are where the paint would be if the op size doesn't overflow
     static const uint8_t gPaintOffsets[LAST_DRAWTYPE_ENUM + 1] = {
         0,  // UNUSED - no paint
@@ -162,7 +168,7 @@ void SkPictureRecord::willSave(SaveFlags flags) {
 
 void SkPictureRecord::recordSave(SaveFlags flags) {
     // op + flags
-    uint32_t size = kSaveSize;
+    size_t size = kSaveSize;
     size_t initialOffset = this->addDraw(SAVE, &size);
     this->addInt(flags);
 
@@ -196,7 +202,7 @@ SkCanvas::SaveLayerStrategy SkPictureRecord::willSaveLayer(const SkRect* bounds,
 void SkPictureRecord::recordSaveLayer(const SkRect* bounds, const SkPaint* paint,
                                       SaveFlags flags) {
     // op + bool for 'bounds'
-    uint32_t size = 2 * kUInt32Size;
+    size_t size = 2 * kUInt32Size;
     if (NULL != bounds) {
         size += sizeof(*bounds); // + rect
     }
@@ -226,7 +232,7 @@ bool SkPictureRecord::isDrawingToLayer() const {
  * Read the op code from 'offset' in 'writer'.
  */
 #ifdef SK_DEBUG
-static DrawType peek_op(SkWriter32* writer, int32_t offset) {
+static DrawType peek_op(SkWriter32* writer, size_t offset) {
     return (DrawType)(writer->readTAt<uint32_t>(offset) >> 24);
 }
 #endif
@@ -234,7 +240,7 @@ static DrawType peek_op(SkWriter32* writer, int32_t offset) {
 /*
  * Read the op code from 'offset' in 'writer' and extract the size too.
  */
-static DrawType peek_op_and_size(SkWriter32* writer, int32_t offset, uint32_t* size) {
+static DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* size) {
     uint32_t peek = writer->readTAt<uint32_t>(offset);
 
     uint32_t op;
@@ -386,8 +392,8 @@ static bool merge_savelayer_paint_into_drawbitmp(SkWriter32* writer,
              DRAW_BITMAP_NINE == dbmInfo.fActualOp ||
              DRAW_BITMAP_RECT_TO_RECT == dbmInfo.fActualOp);
 
-    uint32_t dbmPaintOffset = getPaintOffset(dbmInfo.fActualOp, dbmInfo.fSize);
-    uint32_t slPaintOffset = getPaintOffset(SAVE_LAYER, saveLayerInfo.fSize);
+    size_t dbmPaintOffset = getPaintOffset(dbmInfo.fActualOp, dbmInfo.fSize);
+    size_t slPaintOffset = getPaintOffset(SAVE_LAYER, saveLayerInfo.fSize);
 
     // we have a match, now we need to get the paints involved
     uint32_t dbmPaintId = writer->readTAt<uint32_t>(dbmInfo.fOffset + dbmPaintOffset);
@@ -655,12 +661,11 @@ void SkPictureRecord::willRestore() {
 }
 
 void SkPictureRecord::recordRestore(bool fillInSkips) {
-    uint32_t initialOffset, size;
     if (fillInSkips) {
         this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
     }
-    size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
-    initialOffset = this->addDraw(RESTORE, &size);
+    size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
+    size_t initialOffset = this->addDraw(RESTORE, &size);
     this->validate(initialOffset, size);
 }
 
@@ -668,7 +673,7 @@ void SkPictureRecord::recordTranslate(const SkMatrix& m) {
     SkASSERT(SkMatrix::kTranslate_Mask == m.getType());
 
     // op + dx + dy
-    uint32_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
+    size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
     size_t initialOffset = this->addDraw(TRANSLATE, &size);
     this->addScalar(m.getTranslateX());
     this->addScalar(m.getTranslateY());
@@ -679,7 +684,7 @@ void SkPictureRecord::recordScale(const SkMatrix& m) {
     SkASSERT(SkMatrix::kScale_Mask == m.getType());
 
     // op + sx + sy
-    uint32_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
+    size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
     size_t initialOffset = this->addDraw(SCALE, &size);
     this->addScalar(m.getScaleX());
     this->addScalar(m.getScaleY());
@@ -709,7 +714,7 @@ void SkPictureRecord::didConcat(const SkMatrix& matrix) {
 void SkPictureRecord::recordConcat(const SkMatrix& matrix) {
     this->validate(fWriter.bytesWritten(), 0);
     // op + matrix
-    uint32_t size = kUInt32Size + matrix.writeToMemory(NULL);
+    size_t size = kUInt32Size + matrix.writeToMemory(NULL);
     size_t initialOffset = this->addDraw(CONCAT, &size);
     this->addMatrix(matrix);
     this->validate(initialOffset, size);
@@ -722,7 +727,7 @@ void SkPictureRecord::didSetMatrix(const SkMatrix& matrix) {
 #else
     this->validate(fWriter.bytesWritten(), 0);
     // op + matrix
-    uint32_t size = kUInt32Size + matrix.writeToMemory(NULL);
+    size_t size = kUInt32Size + matrix.writeToMemory(NULL);
     size_t initialOffset = this->addDraw(SET_MATRIX, &size);
     this->addMatrix(matrix);
     this->validate(initialOffset, size);
@@ -772,7 +777,7 @@ void SkPictureRecord::beginRecording() {
     // we have to call this *after* our constructor, to ensure that it gets
     // recorded. This is balanced by restoreToCount() call from endRecording,
     // which in-turn calls our overridden restore(), so those get recorded too.
-    fInitialSaveCount = this->save(kMatrixClip_SaveFlag);
+    fInitialSaveCount = this->save();
 }
 
 void SkPictureRecord::endRecording() {
@@ -790,7 +795,7 @@ int SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
     return offset;
 }
 #else
-int SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
+size_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
     if (fRestoreOffsetStack.isEmpty()) {
         return -1;
     }
@@ -816,7 +821,7 @@ int SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
 
     size_t offset = fWriter.bytesWritten();
     this->addInt(prevOffset);
-    fRestoreOffsetStack.top() = offset;
+    fRestoreOffsetStack.top() = SkToU32(offset);
     return offset;
 }
 #endif
@@ -831,9 +836,9 @@ void SkPictureRecord::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeSt
     this->INHERITED::onClipRect(rect, op, edgeStyle);
 }
 
-int SkPictureRecord::recordClipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
+size_t SkPictureRecord::recordClipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
     // id + rect + clip params
-    uint32_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
+    size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
 #ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
     size += kUInt32Size;    // + restore offset
 #else
@@ -846,7 +851,7 @@ int SkPictureRecord::recordClipRect(const SkRect& rect, SkRegion::Op op, bool do
     size_t initialOffset = this->addDraw(CLIP_RECT, &size);
     this->addRect(rect);
     this->addInt(ClipParams_pack(op, doAA));
-    int offset = this->recordRestoreOffsetPlaceholder(op);
+    size_t offset = this->recordRestoreOffsetPlaceholder(op);
 
     this->validate(initialOffset, size);
     return offset;
@@ -866,9 +871,9 @@ void SkPictureRecord::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdg
     }
 }
 
-int SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
+size_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
     // op + rrect + clip params
-    uint32_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
+    size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
 #ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
     size += kUInt32Size;    // + restore offset
 #else
@@ -881,7 +886,7 @@ int SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool
     size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
     this->addRRect(rrect);
     this->addInt(ClipParams_pack(op, doAA));
-    int offset = recordRestoreOffsetPlaceholder(op);
+    size_t offset = recordRestoreOffsetPlaceholder(op);
     this->validate(initialOffset, size);
     return offset;
 }
@@ -903,9 +908,9 @@ void SkPictureRecord::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeSt
     }
 }
 
-int SkPictureRecord::recordClipPath(int pathID, SkRegion::Op op, bool doAA) {
+size_t SkPictureRecord::recordClipPath(int pathID, SkRegion::Op op, bool doAA) {
     // op + path index + clip params
-    uint32_t size = 3 * kUInt32Size;
+    size_t size = 3 * kUInt32Size;
 #ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
     size += kUInt32Size;    // + restore offset
 #else
@@ -918,7 +923,7 @@ int SkPictureRecord::recordClipPath(int pathID, SkRegion::Op op, bool doAA) {
     size_t initialOffset = this->addDraw(CLIP_PATH, &size);
     this->addInt(pathID);
     this->addInt(ClipParams_pack(op, doAA));
-    int offset = recordRestoreOffsetPlaceholder(op);
+    size_t offset = recordRestoreOffsetPlaceholder(op);
     this->validate(initialOffset, size);
     return offset;
 }
@@ -933,9 +938,9 @@ void SkPictureRecord::onClipRegion(const SkRegion& region, SkRegion::Op op) {
     this->INHERITED::onClipRegion(region, op);
 }
 
-int SkPictureRecord::recordClipRegion(const SkRegion& region, SkRegion::Op op) {
+size_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkRegion::Op op) {
     // op + clip params + region
-    uint32_t size = 2 * kUInt32Size + region.writeToMemory(NULL);
+    size_t size = 2 * kUInt32Size + region.writeToMemory(NULL);
 #ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
     size += kUInt32Size;    // + restore offset
 #else
@@ -948,7 +953,7 @@ int SkPictureRecord::recordClipRegion(const SkRegion& region, SkRegion::Op op) {
     size_t initialOffset = this->addDraw(CLIP_REGION, &size);
     this->addRegion(region);
     this->addInt(ClipParams_pack(op, false));
-    int offset = this->recordRestoreOffsetPlaceholder(op);
+    size_t offset = this->recordRestoreOffsetPlaceholder(op);
 
     this->validate(initialOffset, size);
     return offset;
@@ -961,7 +966,7 @@ void SkPictureRecord::clear(SkColor color) {
 #endif
 
     // op + color
-    uint32_t size = 2 * kUInt32Size;
+    size_t size = 2 * kUInt32Size;
     size_t initialOffset = this->addDraw(DRAW_CLEAR, &size);
     this->addInt(color);
     this->validate(initialOffset, size);
@@ -974,7 +979,7 @@ void SkPictureRecord::drawPaint(const SkPaint& paint) {
 #endif
 
     // op + paint index
-    uint32_t size = 2 * kUInt32Size;
+    size_t size = 2 * kUInt32Size;
     size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
     SkASSERT(initialOffset+getPaintOffset(DRAW_PAINT, size) == fWriter.bytesWritten());
     this->addPaint(paint);
@@ -989,12 +994,12 @@ void SkPictureRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts
 #endif
 
     // op + paint index + mode + count + point data
-    uint32_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
+    size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
     size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
     SkASSERT(initialOffset+getPaintOffset(DRAW_POINTS, size) == fWriter.bytesWritten());
     this->addPaint(paint);
     this->addInt(mode);
-    this->addInt(count);
+    this->addInt(SkToInt(count));
     fWriter.writeMul4(pts, count * sizeof(SkPoint));
     this->validate(initialOffset, size);
 }
@@ -1006,7 +1011,7 @@ void SkPictureRecord::drawOval(const SkRect& oval, const SkPaint& paint) {
 #endif
 
     // op + paint index + rect
-    uint32_t size = 2 * kUInt32Size + sizeof(oval);
+    size_t size = 2 * kUInt32Size + sizeof(oval);
     size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
     SkASSERT(initialOffset+getPaintOffset(DRAW_OVAL, size) == fWriter.bytesWritten());
     this->addPaint(paint);
@@ -1021,7 +1026,7 @@ void SkPictureRecord::drawRect(const SkRect& rect, const SkPaint& paint) {
 #endif
 
     // op + paint index + rect
-    uint32_t size = 2 * kUInt32Size + sizeof(rect);
+    size_t size = 2 * kUInt32Size + sizeof(rect);
     size_t initialOffset = this->addDraw(DRAW_RECT, &size);
     SkASSERT(initialOffset+getPaintOffset(DRAW_RECT, size) == fWriter.bytesWritten());
     this->addPaint(paint);
@@ -1035,15 +1040,14 @@ void SkPictureRecord::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
     fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
 #endif
 
-    if (rrect.isRect()) {
+    if (rrect.isRect() && kBeClever) {
         this->SkPictureRecord::drawRect(rrect.getBounds(), paint);
-    } else if (rrect.isOval()) {
+    } else if (rrect.isOval() && kBeClever) {
         this->SkPictureRecord::drawOval(rrect.getBounds(), paint);
     } else {
         // op + paint index + rrect
-        uint32_t initialOffset, size;
-        size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
-        initialOffset = this->addDraw(DRAW_RRECT, &size);
+        size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
+        size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
         SkASSERT(initialOffset+getPaintOffset(DRAW_RRECT, size) == fWriter.bytesWritten());
         this->addPaint(paint);
         this->addRRect(rrect);
@@ -1059,9 +1063,8 @@ void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
 #endif
 
     // op + paint index + rrects
-    uint32_t initialOffset, size;
-    size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
-    initialOffset = this->addDraw(DRAW_DRRECT, &size);
+    size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
+    size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
     SkASSERT(initialOffset+getPaintOffset(DRAW_DRRECT, size) == fWriter.bytesWritten());
     this->addPaint(paint);
     this->addRRect(outer);
@@ -1071,12 +1074,21 @@ void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
 
 void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) {
 
+    if (paint.isAntiAlias() && !path.isConvex()) {
+        fPicture->incAAConcavePaths();
+
+        if (SkPaint::kStroke_Style == paint.getStyle() &&
+            0 == paint.getStrokeWidth()) {
+            fPicture->incAAHairlineConcavePaths();
+        }
+    }
+
 #ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
     fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
 #endif
 
     // op + paint index + path index
-    uint32_t size = 3 * kUInt32Size;
+    size_t size = 3 * kUInt32Size;
     size_t initialOffset = this->addDraw(DRAW_PATH, &size);
     SkASSERT(initialOffset+getPaintOffset(DRAW_PATH, size) == fWriter.bytesWritten());
     this->addPaint(paint);
@@ -1086,7 +1098,7 @@ void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) {
 
 void SkPictureRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
                                  const SkPaint* paint = NULL) {
-    if (bitmap.drawsNothing()) {
+    if (bitmap.drawsNothing() && kBeClever) {
         return;
     }
 
@@ -1095,21 +1107,20 @@ void SkPictureRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar
 #endif
 
     // op + paint index + bitmap index + left + top
-    uint32_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
+    size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
     size_t initialOffset = this->addDraw(DRAW_BITMAP, &size);
     SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP, size) == fWriter.bytesWritten());
     this->addPaintPtr(paint);
-    int bitmapID = this->addBitmap(bitmap);
+    this->addBitmap(bitmap);
     this->addScalar(left);
     this->addScalar(top);
     this->validate(initialOffset, size);
-    this->trackBitmapUse(bitmapID, initialOffset);
 }
 
 void SkPictureRecord::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
                                            const SkRect& dst, const SkPaint* paint,
                                            DrawBitmapRectFlags flags) {
-    if (bitmap.drawsNothing()) {
+    if (bitmap.drawsNothing() && kBeClever) {
         return;
     }
 
@@ -1117,7 +1128,7 @@ void SkPictureRecord::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect*
     fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
 #endif
     // id + paint index + bitmap index + bool for 'src' + flags
-    uint32_t size = 5 * kUInt32Size;
+    size_t size = 5 * kUInt32Size;
     if (NULL != src) {
         size += sizeof(*src);   // + rect
     }
@@ -1127,17 +1138,16 @@ void SkPictureRecord::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect*
     SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP_RECT_TO_RECT, size)
              == fWriter.bytesWritten());
     this->addPaintPtr(paint);
-    int bitmapID = this->addBitmap(bitmap);
+    this->addBitmap(bitmap);
     this->addRectPtr(src);  // may be null
     this->addRect(dst);
     this->addInt(flags);
     this->validate(initialOffset, size);
-    this->trackBitmapUse(bitmapID, initialOffset);
 }
 
 void SkPictureRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
                                        const SkPaint* paint) {
-    if (bitmap.drawsNothing()) {
+    if (bitmap.drawsNothing() && kBeClever) {
         return;
     }
 
@@ -1146,19 +1156,18 @@ void SkPictureRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m
 #endif
 
     // id + paint index + bitmap index + matrix
-    uint32_t size = 3 * kUInt32Size + matrix.writeToMemory(NULL);
+    size_t size = 3 * kUInt32Size + matrix.writeToMemory(NULL);
     size_t initialOffset = this->addDraw(DRAW_BITMAP_MATRIX, &size);
     SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP_MATRIX, size) == fWriter.bytesWritten());
     this->addPaintPtr(paint);
-    int bitmapID = this->addBitmap(bitmap);
+    this->addBitmap(bitmap);
     this->addMatrix(matrix);
     this->validate(initialOffset, size);
-    this->trackBitmapUse(bitmapID, initialOffset);
 }
 
 void SkPictureRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
                                      const SkRect& dst, const SkPaint* paint) {
-    if (bitmap.drawsNothing()) {
+    if (bitmap.drawsNothing() && kBeClever) {
         return;
     }
 
@@ -1167,20 +1176,19 @@ void SkPictureRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& cent
 #endif
 
     // op + paint index + bitmap id + center + dst rect
-    uint32_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst);
+    size_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst);
     size_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size);
     SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP_NINE, size) == fWriter.bytesWritten());
     this->addPaintPtr(paint);
-    int bitmapID = this->addBitmap(bitmap);
+    this->addBitmap(bitmap);
     this->addIRect(center);
     this->addRect(dst);
     this->validate(initialOffset, size);
-    this->trackBitmapUse(bitmapID, initialOffset);
 }
 
 void SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
                                  const SkPaint* paint = NULL) {
-    if (bitmap.drawsNothing()) {
+    if (bitmap.drawsNothing() && kBeClever) {
         return;
     }
 
@@ -1189,15 +1197,14 @@ void SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
 #endif
 
     // op + paint index + bitmap index + left + top
-    uint32_t size = 5 * kUInt32Size;
+    size_t size = 5 * kUInt32Size;
     size_t initialOffset = this->addDraw(DRAW_SPRITE, &size);
     SkASSERT(initialOffset+getPaintOffset(DRAW_SPRITE, size) == fWriter.bytesWritten());
     this->addPaintPtr(paint);
-    int bitmapID = this->addBitmap(bitmap);
+    this->addBitmap(bitmap);
     this->addInt(left);
     this->addInt(top);
     this->validate(initialOffset, size);
-    this->trackBitmapUse(bitmapID, initialOffset);
 }
 
 void SkPictureRecord::ComputeFontMetricsTopBottom(const SkPaint& paint, SkScalar topbot[2]) {
@@ -1219,17 +1226,17 @@ void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint, const SkFlat
     this->addScalar(flat.topBot()[1] + maxY);
 }
 
-void SkPictureRecord::drawText(const void* text, size_t byteLength, SkScalar x,
-                      SkScalar y, const SkPaint& paint) {
+void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
+                                 const SkPaint& paint) {
 
 #ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
     fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
 #endif
 
-    bool fast = !paint.isVerticalText() && paint.canComputeFastBounds();
+    bool fast = !paint.isVerticalText() && paint.canComputeFastBounds() && kBeClever;
 
     // op + paint index + length + 'length' worth of chars + x + y
-    uint32_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
+    size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
     if (fast) {
         size += 2 * sizeof(SkScalar); // + top & bottom
     }
@@ -1248,14 +1255,14 @@ void SkPictureRecord::drawText(const void* text, size_t byteLength, SkScalar x,
     this->validate(initialOffset, size);
 }
 
-void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
-                         const SkPoint pos[], const SkPaint& paint) {
+void SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
+                                    const SkPaint& paint) {
 
 #ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
     fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
 #endif
 
-    size_t points = paint.countText(text, byteLength);
+    int points = paint.countText(text, byteLength);
     if (0 == points)
         return;
 
@@ -1265,7 +1272,7 @@ void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
     // check if the caller really should have used drawPosTextH()
     {
         const SkScalar firstY = pos[0].fY;
-        for (size_t index = 1; index < points; index++) {
+        for (int index = 1; index < points; index++) {
             if (pos[index].fY != firstY) {
                 canUseDrawH = false;
                 if (pos[index].fY < minY) {
@@ -1277,11 +1284,11 @@ void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
         }
     }
 
-    bool fastBounds = !paint.isVerticalText() && paint.canComputeFastBounds();
-    bool fast = canUseDrawH && fastBounds;
+    bool fastBounds = !paint.isVerticalText() && paint.canComputeFastBounds() && kBeClever;
+    bool fast = canUseDrawH && fastBounds && kBeClever;
 
     // op + paint index + length + 'length' worth of data + num points
-    uint32_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
+    size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
     if (canUseDrawH) {
         if (fast) {
             size += 2 * sizeof(SkScalar); // + top & bottom
@@ -1322,7 +1329,7 @@ void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
         }
         this->addScalar(pos[0].fY);
         SkScalar* xptr = (SkScalar*)fWriter.reserve(points * sizeof(SkScalar));
-        for (size_t index = 0; index < points; index++)
+        for (int index = 0; index < points; index++)
             *xptr++ = pos[index].fX;
     } else {
         fWriter.writeMul4(pos, points * sizeof(SkPoint));
@@ -1337,10 +1344,8 @@ void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
     this->validate(initialOffset, size);
 }
 
-void SkPictureRecord::drawPosTextH(const void* text, size_t byteLength,
-                          const SkScalar xpos[], SkScalar constY,
-                          const SkPaint& paint) {
-
+void SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
+                                     SkScalar constY, const SkPaint& paint) {
 #ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
     fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
 #endif
@@ -1352,14 +1357,15 @@ void SkPictureRecord::drawPosTextH(const void* text, size_t byteLength,
 void SkPictureRecord::drawPosTextHImpl(const void* text, size_t byteLength,
                           const SkScalar xpos[], SkScalar constY,
                           const SkPaint& paint, const SkFlatData* flatPaintData) {
-    size_t points = paint.countText(text, byteLength);
-    if (0 == points)
+    int points = paint.countText(text, byteLength);
+    if (0 == points && kBeClever) {
         return;
+    }
 
-    bool fast = !paint.isVerticalText() && paint.canComputeFastBounds();
+    bool fast = !paint.isVerticalText() && paint.canComputeFastBounds() && kBeClever;
 
     // op + paint index + length + 'length' worth of data + num points
-    uint32_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
+    size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
     if (fast) {
         size += 2 * sizeof(SkScalar); // + top & bottom
     }
@@ -1388,17 +1394,15 @@ void SkPictureRecord::drawPosTextHImpl(const void* text, size_t byteLength,
     this->validate(initialOffset, size);
 }
 
-void SkPictureRecord::drawTextOnPath(const void* text, size_t byteLength,
-                            const SkPath& path, const SkMatrix* matrix,
-                            const SkPaint& paint) {
-
+void SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
+                                       const SkMatrix* matrix, const SkPaint& paint) {
 #ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
     fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
 #endif
 
     // op + paint index + length + 'length' worth of data + path index + matrix
     const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
-    uint32_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(NULL);
+    size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(NULL);
     size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
     SkASSERT(initialOffset+getPaintOffset(DRAW_TEXT_ON_PATH, size) == fWriter.bytesWritten());
     this->addPaint(paint);
@@ -1415,7 +1419,7 @@ void SkPictureRecord::drawPicture(SkPicture& picture) {
 #endif
 
     // op + picture index
-    uint32_t size = 2 * kUInt32Size;
+    size_t size = 2 * kUInt32Size;
     size_t initialOffset = this->addDraw(DRAW_PICTURE, &size);
     this->addPicture(picture);
     this->validate(initialOffset, size);
@@ -1449,7 +1453,7 @@ void SkPictureRecord::drawVertices(VertexMode vmode, int vertexCount,
     }
 
     // op + paint index + flags + vmode + vCount + vertices
-    uint32_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
+    size_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
     if (flags & DRAW_VERTICES_HAS_TEXS) {
         size += vertexCount * sizeof(SkPoint);  // + uvs
     }
@@ -1496,17 +1500,17 @@ void SkPictureRecord::drawData(const void* data, size_t length) {
 #endif
 
     // op + length + 'length' worth of data
-    uint32_t size = 2 * kUInt32Size + SkAlign4(length);
+    size_t size = 2 * kUInt32Size + SkAlign4(length);
     size_t initialOffset = this->addDraw(DRAW_DATA, &size);
-    this->addInt(length);
+    this->addInt(SkToInt(length));
     fWriter.writePad(data, length);
     this->validate(initialOffset, size);
 }
 
 void SkPictureRecord::beginCommentGroup(const char* description) {
     // op/size + length of string + \0 terminated chars
-    int length = strlen(description);
-    uint32_t size = 2 * kUInt32Size + SkAlign4(length + 1);
+    size_t length = strlen(description);
+    size_t size = 2 * kUInt32Size + SkAlign4(length + 1);
     size_t initialOffset = this->addDraw(BEGIN_COMMENT_GROUP, &size);
     fWriter.writeString(description, length);
     this->validate(initialOffset, size);
@@ -1514,9 +1518,9 @@ void SkPictureRecord::beginCommentGroup(const char* description) {
 
 void SkPictureRecord::addComment(const char* kywd, const char* value) {
     // op/size + 2x length of string + 2x \0 terminated chars
-    int kywdLen = strlen(kywd);
-    int valueLen = strlen(value);
-    uint32_t size = 3 * kUInt32Size + SkAlign4(kywdLen + 1) + SkAlign4(valueLen + 1);
+    size_t kywdLen = strlen(kywd);
+    size_t valueLen = strlen(value);
+    size_t size = 3 * kUInt32Size + SkAlign4(kywdLen + 1) + SkAlign4(valueLen + 1);
     size_t initialOffset = this->addDraw(COMMENT, &size);
     fWriter.writeString(kywd, kywdLen);
     fWriter.writeString(value, valueLen);
@@ -1525,7 +1529,7 @@ void SkPictureRecord::addComment(const char* kywd, const char* value) {
 
 void SkPictureRecord::endCommentGroup() {
     // op/size
-    uint32_t size = 1 * kUInt32Size;
+    size_t size = 1 * kUInt32Size;
     size_t initialOffset = this->addDraw(END_COMMENT_GROUP, &size);
     this->validate(initialOffset, size);
 }
@@ -1533,13 +1537,13 @@ void SkPictureRecord::endCommentGroup() {
 // [op/size] [rect] [skip offset]
 static const uint32_t kPushCullOpSize = 2 * kUInt32Size + sizeof(SkRect);
 void SkPictureRecord::onPushCull(const SkRect& cullRect) {
-    uint32_t size = kPushCullOpSize;
+    size_t size = kPushCullOpSize;
     size_t initialOffset = this->addDraw(PUSH_CULL, &size);
     // PUSH_CULL's size should stay constant (used to rewind).
     SkASSERT(size == kPushCullOpSize);
 
     this->addRect(cullRect);
-    fCullOffsetStack.push(fWriter.bytesWritten());
+    fCullOffsetStack.push(SkToU32(fWriter.bytesWritten()));
     this->addInt(0);
     this->validate(initialOffset, size);
 }
@@ -1551,7 +1555,7 @@ void SkPictureRecord::onPopCull() {
     fCullOffsetStack.pop();
 
     // Collapse empty push/pop pairs.
-    if ((size_t)(cullSkipOffset + kUInt32Size) == fWriter.bytesWritten()) {
+    if ((size_t)(cullSkipOffset + kUInt32Size) == fWriter.bytesWritten() && kBeClever) {
         SkASSERT(fWriter.bytesWritten() >= kPushCullOpSize);
         SkASSERT(PUSH_CULL == peek_op(&fWriter, fWriter.bytesWritten() - kPushCullOpSize));
         fWriter.rewindToOffset(fWriter.bytesWritten() - kPushCullOpSize);
@@ -1559,11 +1563,11 @@ void SkPictureRecord::onPopCull() {
     }
 
     // op only
-    uint32_t size = kUInt32Size;
+    size_t size = kUInt32Size;
     size_t initialOffset = this->addDraw(POP_CULL, &size);
 
     // update the cull skip offset to point past this op.
-    fWriter.overwriteTAt<uint32_t>(cullSkipOffset, fWriter.bytesWritten());
+    fWriter.overwriteTAt<uint32_t>(cullSkipOffset, SkToU32(fWriter.bytesWritten()));
 
     this->validate(initialOffset, size);
 }
@@ -1571,27 +1575,7 @@ void SkPictureRecord::onPopCull() {
 ///////////////////////////////////////////////////////////////////////////////
 
 SkSurface* SkPictureRecord::onNewSurface(const SkImageInfo& info) {
-    return SkSurface::NewPicture(info.fWidth, info.fHeight);
-}
-
-void SkPictureRecord::trackBitmapUse(int bitmapID, size_t offset) {
-#ifndef SK_ALLOW_BITMAP_TRACKING
-    return;
-#endif
-
-    if (!(fRecordFlags & SkPicture::kOptimizeForClippedPlayback_RecordingFlag)) {
-        return;
-    }
-
-    if (SkBitmapHeap::INVALID_SLOT == bitmapID) {
-        return;
-    }
-
-    if (NULL == fBitmapUseOffsets) {
-        fBitmapUseOffsets.reset(SkNEW(SkOffsetTable));
-    }
-
-    fBitmapUseOffsets->add(bitmapID, offset);
+    return NULL;
 }
 
 int SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
@@ -1613,6 +1597,10 @@ const SkFlatData* SkPictureRecord::getFlatPaintData(const SkPaint& paint) {
 }
 
 const SkFlatData* SkPictureRecord::addPaintPtr(const SkPaint* paint) {
+    if (NULL != paint && NULL != paint->getPathEffect()) {
+        fPicture->incPaintWithPathEffectUses();
+    }
+
     const SkFlatData* data = paint ? getFlatPaintData(*paint) : NULL;
     this->addFlatPaint(data);
     return data;
@@ -1624,14 +1612,7 @@ void SkPictureRecord::addFlatPaint(const SkFlatData* flatPaint) {
 }
 
 int SkPictureRecord::addPathToHeap(const SkPath& path) {
-    if (NULL == fPathHeap) {
-        fPathHeap = SkNEW(SkPathHeap);
-    }
-#ifdef SK_DEDUP_PICTURE_PATHS
-    return fPathHeap->insert(path);
-#else
-    return fPathHeap->append(path);
-#endif
+    return fPicture->addPathToHeap(path);
 }
 
 void SkPictureRecord::addPath(const SkPath& path) {
@@ -1707,7 +1688,7 @@ void SkPictureRecord::addText(const void* text, size_t byteLength) {
 #ifdef SK_DEBUG_SIZE
     size_t start = fWriter.bytesWritten();
 #endif
-    addInt(byteLength);
+    addInt(SkToInt(byteLength));
     fWriter.writePad(text, byteLength);
 #ifdef SK_DEBUG_SIZE
     fTextBytes += fWriter.bytesWritten() - start;