*/
void swap(SkPicture& other);
+ enum RecordingFlags {
+ /* This flag specifies that when clipPath() is called, the path will
+ be faithfully recorded, but the recording canvas' current clip will
+ only see the path's bounds. This speeds up the recording process
+ without compromising the fidelity of the playback. The only side-
+ effect for recording is that calling getTotalClip() or related
+ clip-query calls will reflect the path's bounds, not the actual
+ path.
+ */
+ kUsePathBoundsForClip_RecordingFlag = 0x01
+ };
+
/** Returns the canvas that records the drawing commands.
+ @param width the base width for the picture, as if the recording
+ canvas' bitmap had this width.
+ @param height the base width for the picture, as if the recording
+ canvas' bitmap had this height.
+ @param recordFlags optional flags that control recording.
@return the picture canvas.
*/
- SkCanvas* beginRecording(int width, int height);
+ SkCanvas* beginRecording(int width, int height, uint32_t recordFlags = 0);
+
/** Returns the recording canvas if one is active, or NULL if recording is
not active. This does not alter the refcnt on the canvas (if present).
*/
class SkAutoPictureRecord : SkNoncopyable {
public:
- SkAutoPictureRecord(SkPicture* pict, int width, int height) {
+ SkAutoPictureRecord(SkPicture* pict, int width, int height,
+ uint32_t recordingFlags = 0) {
fPicture = pict;
- fCanvas = pict->beginRecording(width, height);
+ fCanvas = pict->beginRecording(width, height, recordingFlags);
}
~SkAutoPictureRecord() {
fPicture->endRecording();
///////////////////////////////////////////////////////////////////////////////
-SkCanvas* SkPicture::beginRecording(int width, int height) {
+SkCanvas* SkPicture::beginRecording(int width, int height,
+ uint32_t recordingFlags) {
if (fPlayback) {
SkDELETE(fPlayback);
fPlayback = NULL;
fRecord = NULL;
}
- fRecord = SkNEW(SkPictureRecord);
+ fRecord = SkNEW_ARGS(SkPictureRecord, (recordingFlags));
fWidth = width;
fHeight = height;
#include "SkTypeface.h"
#include <new>
+/* Define this to spew out a debug statement whenever we skip the remainder of
+ a save/restore block because a clip... command returned false (empty).
+ */
+#define SPEW_CLIP_SKIPPINGx
+
SkPicturePlayback::SkPicturePlayback() {
this->init();
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
+#ifdef SPEW_CLIP_SKIPPING
+struct SkipClipRec {
+ int fCount;
+ size_t fSize;
+
+ SkipClipRec() {
+ fCount = 0;
+ fSize = 0;
+ }
+
+ void recordSkip(size_t bytes) {
+ fCount += 1;
+ fSize += bytes;
+ }
+};
+#endif
+
void SkPicturePlayback::draw(SkCanvas& canvas) {
#ifdef ENABLE_TIME_DRAW
SkAutoTime at("SkPicture::draw", 50);
#endif
+
+#ifdef SPEW_CLIP_SKIPPING
+ SkipClipRec skipRect, skipRegion, skipPath;
+#endif
TextContainer text;
fReader.rewind();
SkRegion::Op op = (SkRegion::Op) getInt();
size_t offsetToRestore = getInt();
// HACK (false) until I can handle op==kReplace
- if (!canvas.clipPath(path, op) && false) {
- //SkDebugf("---- skip clipPath for %d bytes\n", offsetToRestore - fReader.offset());
+ if (!canvas.clipPath(path, op)) {
+#ifdef SPEW_CLIP_SKIPPING
+ skipPath.recordSkip(offsetToRestore - fReader.offset());
+#endif
fReader.setOffset(offsetToRestore);
}
} break;
SkRegion::Op op = (SkRegion::Op) getInt();
size_t offsetToRestore = getInt();
if (!canvas.clipRegion(region, op)) {
- //SkDebugf("---- skip clipDeviceRgn for %d bytes\n", offsetToRestore - fReader.offset());
+#ifdef SPEW_CLIP_SKIPPING
+ skipRegion.recordSkip(offsetToRestore - fReader.offset());
+#endif
fReader.setOffset(offsetToRestore);
}
} break;
SkRegion::Op op = (SkRegion::Op) getInt();
size_t offsetToRestore = getInt();
if (!canvas.clipRect(*rect, op)) {
- //SkDebugf("---- skip clipRect for %d bytes\n", offsetToRestore - fReader.offset());
+#ifdef SPEW_CLIP_SKIPPING
+ skipRect.recordSkip(offsetToRestore - fReader.offset());
+#endif
fReader.setOffset(offsetToRestore);
}
} break;
}
}
+#ifdef SPEW_CLIP_SKIPPING
+ {
+ size_t size = skipRect.fSize + skipPath.fSize + skipRegion.fSize;
+ SkDebugf("--- Clip skips %d%% rect:%d path:%d rgn:%d\n",
+ size * 100 / fReader.offset(), skipRect.fCount, skipPath.fCount,
+ skipRegion.fCount);
+ }
+#endif
// this->dumpSize();
}
#define MIN_WRITER_SIZE 16384
#define HEAP_BLOCK_SIZE 4096
-SkPictureRecord::SkPictureRecord() :
- fHeap(HEAP_BLOCK_SIZE), fWriter(MIN_WRITER_SIZE) {
+SkPictureRecord::SkPictureRecord(uint32_t flags) :
+ fHeap(HEAP_BLOCK_SIZE), fWriter(MIN_WRITER_SIZE), fRecordFlags(flags) {
fBitmapIndex = fMatrixIndex = fPaintIndex = fRegionIndex = 1;
#ifdef SK_DEBUG_SIZE
fPointBytes = fRectBytes = fTextBytes = 0;
fRestoreOffsetStack.top() = offset;
validate();
- return this->INHERITED::clipPath(path, op);
+
+ if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) {
+ SkRect bounds;
+ path.computeBounds(&bounds, SkPath::kFast_BoundsType);
+ return this->INHERITED::clipRect(bounds, op);
+ } else {
+ return this->INHERITED::clipPath(path, op);
+ }
}
bool SkPictureRecord::clipRegion(const SkRegion& region, SkRegion::Op op) {
class SkPictureRecord : public SkCanvas {
public:
- SkPictureRecord();
+ SkPictureRecord(uint32_t recordFlags);
virtual ~SkPictureRecord();
// overrides from SkCanvas
SkRefCntRecorder fRCRecorder;
SkRefCntRecorder fTFRecorder;
+ uint32_t fRecordFlags;
+
friend class SkPicturePlayback;
typedef SkCanvas INHERITED;