SkBitmap fBitmap;
+ void setNewSize(const SkISize&); // Used by SkCanvas for resetForNextPicture().
+
typedef SkBaseDevice INHERITED;
};
SkCanvas(const SkIRect& bounds, InitFlags);
SkCanvas(SkBaseDevice*, const SkSurfaceProps*, InitFlags);
+ void resetForNextPicture(const SkIRect& bounds);
+
// needs gettotalclip()
friend class SkCanvasStateUtils;
friend class SkPictureRecorderReplayTester; // for unit testing
void partialReplay(SkCanvas* canvas) const;
+ bool fActivelyRecording;
uint32_t fFlags;
SkRect fCullRect;
SkAutoTUnref<SkBBoxHierarchy> fBBH;
return fBitmap.info();
}
+void SkBitmapDevice::setNewSize(const SkISize& size) {
+ SkASSERT(!fBitmap.pixelRef());
+ fBitmap.setInfo(fBitmap.info().makeWH(size.fWidth, size.fHeight));
+}
+
void SkBitmapDevice::replaceBitmapBackendForRasterSurface(const SkBitmap& bm) {
SkASSERT(bm.width() == fBitmap.width());
SkASSERT(bm.height() == fBitmap.height());
SkDELETE(fPaint);
}
+ void reset(const SkIRect& bounds) {
+ SkASSERT(!fPaint);
+ SkASSERT(!fNext);
+ SkASSERT(fDevice);
+ fClip.setRect(bounds);
+ }
+
void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip,
const SkClipStack& clipStack, SkRasterClip* updateClip) {
int x = fDevice->getOrigin().x();
SkDELETE(fLayer);
dec_rec();
}
+
+ void reset(const SkIRect& bounds) {
+ SkASSERT(fLayer);
+ SkASSERT(fDeferredSaveCount == 0);
+
+ fMatrix.reset();
+ fRasterClip.setRect(bounds);
+ fLayer->reset(bounds);
+ }
};
class SkDrawIter : public SkDraw {
////////////////////////////////////////////////////////////////////////////
+void SkCanvas::resetForNextPicture(const SkIRect& bounds) {
+ this->restoreToCount(1);
+ fCachedLocalClipBounds.setEmpty();
+ fCachedLocalClipBoundsDirty = true;
+ fClipStack->reset();
+ fMCRec->reset(bounds);
+
+ // We're peering through a lot of structs here. Only at this scope do we
+ // know that the device is an SkBitmapDevice (really an SkNoPixelsBitmapDevice).
+ static_cast<SkBitmapDevice*>(fMCRec->fLayer->fDevice)->setNewSize(bounds.size());
+}
+
SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
fConservativeRasterClip = SkToBool(flags & kConservativeRasterClip_InitFlag);
fCachedLocalClipBounds.setEmpty();
#include "SkRecordOpts.h"
#include "SkTypes.h"
-SkPictureRecorder::SkPictureRecorder() {}
+SkPictureRecorder::SkPictureRecorder() {
+ fActivelyRecording = false;
+ fRecorder.reset(SkNEW_ARGS(SkRecorder, (nullptr, SkRect::MakeWH(0,0))));
+}
SkPictureRecorder::~SkPictureRecorder() {}
}
fRecord.reset(SkNEW(SkRecord));
- fRecorder.reset(SkNEW_ARGS(SkRecorder, (fRecord.get(), cullRect)));
+ fRecorder->reset(fRecord.get(), cullRect);
+ fActivelyRecording = true;
return this->getRecordingCanvas();
}
SkCanvas* SkPictureRecorder::getRecordingCanvas() {
- return fRecorder.get();
+ return fActivelyRecording ? fRecorder.get() : nullptr;
}
SkPicture* SkPictureRecorder::endRecordingAsPicture() {
+ fActivelyRecording = false;
+ fRecorder->restoreToCount(1); // If we were missing any restores, add them now.
// TODO: delay as much of this work until just before first playback?
SkRecordOptimize(fRecord);
}
// release our refs now, so only the picture will be the owner.
- fRecorder.reset(NULL);
fRecord.reset(NULL);
fBBH.reset(NULL);
};
SkDrawable* SkPictureRecorder::endRecordingAsDrawable() {
+ fActivelyRecording = false;
+ fRecorder->restoreToCount(1); // If we were missing any restores, add them now.
// TODO: delay as much of this work until just before first playback?
SkRecordOptimize(fRecord);
SkToBool(fFlags & kComputeSaveLayerInfo_RecordFlag)));
// release our refs now, so only the drawable will be the owner.
- fRecorder.reset(NULL);
fRecord.reset(NULL);
fBBH.reset(NULL);
: SkCanvas(bounds.roundOut(), SkCanvas::kConservativeRasterClip_InitFlag)
, fRecord(record) {}
+void SkRecorder::reset(SkRecord* record, const SkRect& bounds) {
+ this->forgetRecord();
+ fRecord = record;
+ this->resetForNextPicture(bounds.roundOut());
+}
+
void SkRecorder::forgetRecord() {
fDrawableList.reset(NULL);
fRecord = NULL;
SkRecorder(SkRecord*, int width, int height); // legacy version
SkRecorder(SkRecord*, const SkRect& bounds);
+ void reset(SkRecord*, const SkRect& bounds);
+
SkDrawableList* getDrawableList() const { return fDrawableList.get(); }
SkDrawableList* detachDrawableList() { return fDrawableList.detach(); }
REPORTER_ASSERT(r, mut.pixelRef()->unique());
REPORTER_ASSERT(r, immut.pixelRef()->unique());
}
+
+// getRecordingCanvas() should return a SkCanvas when recording, null when not recording.
+DEF_TEST(Picture_getRecordingCanvas, r) {
+ SkPictureRecorder rec;
+ REPORTER_ASSERT(r, !rec.getRecordingCanvas());
+ for (int i = 0; i < 3; i++) {
+ rec.beginRecording(100, 100);
+ REPORTER_ASSERT(r, rec.getRecordingCanvas());
+ rec.endRecording()->unref();
+ REPORTER_ASSERT(r, !rec.getRecordingCanvas());
+ }
+}