| Index: src/core/SkCanvas.cpp
|
| diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
|
| index 8426f090ec5949653ab516ffca3f7d33a317c338..8fe572010b5872dad067848cc3e155c1a3b0d53d 100644
|
| --- a/src/core/SkCanvas.cpp
|
| +++ b/src/core/SkCanvas.cpp
|
| @@ -198,23 +198,25 @@ public:
|
| DeviceCM* fTopLayer;
|
| SkRasterClip fRasterClip;
|
| SkMatrix fMatrix;
|
| - int fDeferredSaveCount;
|
| + int fSaveCount; // The count of SkCanvas::save() calls when this rec was created.
|
|
|
| - MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) {
|
| + MCRec(bool conservativeRasterClip, int saveCount)
|
| + : fRasterClip(conservativeRasterClip)
|
| + , fSaveCount(saveCount) {
|
| fFilter = NULL;
|
| fLayer = NULL;
|
| fTopLayer = NULL;
|
| fMatrix.reset();
|
| - fDeferredSaveCount = 0;
|
|
|
| // don't bother initializing fNext
|
| inc_rec();
|
| }
|
| - MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip), fMatrix(prev.fMatrix) {
|
| + MCRec(const MCRec& prev, int saveCount)
|
| + : fRasterClip(prev.fRasterClip), fMatrix(prev.fMatrix)
|
| + , fSaveCount(saveCount) {
|
| fFilter = SkSafeRef(prev.fFilter);
|
| fLayer = NULL;
|
| fTopLayer = prev.fTopLayer;
|
| - fDeferredSaveCount = 0;
|
|
|
| // don't bother initializing fNext
|
| inc_rec();
|
| @@ -436,7 +438,7 @@ SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
|
| fMetaData = NULL;
|
|
|
| fMCRec = (MCRec*)fMCStack.push_back();
|
| - new (fMCRec) MCRec(fConservativeRasterClip);
|
| + new (fMCRec) MCRec(fConservativeRasterClip, fSaveCount);
|
|
|
| fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, NULL, NULL, fConservativeRasterClip));
|
| fMCRec->fTopLayer = fMCRec->fLayer;
|
| @@ -545,7 +547,6 @@ SkCanvas::SkCanvas(const SkBitmap& bitmap)
|
| SkCanvas::~SkCanvas() {
|
| // free up the contents of our deque
|
| this->restoreToCount(1); // restore everything but the last
|
| -
|
| this->internalRestore(); // restore the last, since we're going away
|
|
|
| SkDELETE(fMetaData);
|
| @@ -752,31 +753,17 @@ void SkCanvas::updateDeviceCMCache() {
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|
| void SkCanvas::checkForDeferredSave() {
|
| - if (fMCRec->fDeferredSaveCount > 0) {
|
| - fMCRec->fDeferredSaveCount -= 1;
|
| + if (fMCRec->fSaveCount < fSaveCount) {
|
| this->doSave();
|
| }
|
| }
|
|
|
| int SkCanvas::getSaveCount() const {
|
| -#ifdef SK_DEBUG
|
| - int count = 0;
|
| - SkDeque::Iter iter(fMCStack, SkDeque::Iter::kFront_IterStart);
|
| - for (;;) {
|
| - const MCRec* rec = (const MCRec*)iter.next();
|
| - if (!rec) {
|
| - break;
|
| - }
|
| - count += 1 + rec->fDeferredSaveCount;
|
| - }
|
| - SkASSERT(count == fSaveCount);
|
| -#endif
|
| return fSaveCount;
|
| }
|
|
|
| int SkCanvas::save() {
|
| fSaveCount += 1;
|
| - fMCRec->fDeferredSaveCount += 1;
|
| return this->getSaveCount() - 1; // return our prev value
|
| }
|
|
|
| @@ -786,20 +773,23 @@ void SkCanvas::doSave() {
|
| }
|
|
|
| void SkCanvas::restore() {
|
| - if (fMCRec->fDeferredSaveCount > 0) {
|
| - SkASSERT(fSaveCount > 1);
|
| - fSaveCount -= 1;
|
| - fMCRec->fDeferredSaveCount -= 1;
|
| - } else {
|
| - // check for underflow
|
| + int deferredSaveCount = fSaveCount - fMCRec->fSaveCount;
|
| + SkASSERT(deferredSaveCount >= 0);
|
| + if (deferredSaveCount == 0) {
|
| + // Check if the client tried to restore() too many times.
|
| if (fMCStack.count() > 1) {
|
| this->willRestore();
|
| - SkASSERT(fSaveCount > 1);
|
| - fSaveCount -= 1;
|
| this->internalRestore();
|
| + fSaveCount -= 1;
|
| this->didRestore();
|
| }
|
| + } else {
|
| + // The topmost save was deferred.
|
| + fSaveCount -= 1;
|
| }
|
| +
|
| + // Note: we can not detect the case where errorneous SkCanvas::restore()
|
| + // is called within the SkDrawLooper callback.
|
| }
|
|
|
| void SkCanvas::restoreToCount(int count) {
|
| @@ -816,9 +806,8 @@ void SkCanvas::restoreToCount(int count) {
|
|
|
| void SkCanvas::internalSave() {
|
| MCRec* newTop = (MCRec*)fMCStack.push_back();
|
| - new (newTop) MCRec(*fMCRec); // balanced in restore()
|
| + new (newTop) MCRec(*fMCRec, fSaveCount); // balanced in restore()
|
| fMCRec = newTop;
|
| -
|
| fClipStack->save();
|
| }
|
|
|
| @@ -879,7 +868,7 @@ int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
|
| bounds = NULL;
|
| }
|
| SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag);
|
| - fSaveCount += 1;
|
| + fSaveCount++;
|
| this->internalSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag, strategy);
|
| return this->getSaveCount() - 1;
|
| }
|
| @@ -889,7 +878,7 @@ int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags fl
|
| bounds = NULL;
|
| }
|
| SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, flags);
|
| - fSaveCount += 1;
|
| + fSaveCount++;
|
| this->internalSaveLayer(bounds, paint, flags, strategy);
|
| return this->getSaveCount() - 1;
|
| }
|
| @@ -977,6 +966,7 @@ int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
|
|
|
| void SkCanvas::internalRestore() {
|
| SkASSERT(fMCStack.count() != 0);
|
| + SkASSERT(fMCRec->fSaveCount == fSaveCount);
|
|
|
| fDeviceCMDirty = true;
|
| fCachedLocalClipBoundsDirty = true;
|
| @@ -1007,6 +997,7 @@ void SkCanvas::internalRestore() {
|
| }
|
| SkDELETE(layer);
|
| }
|
| + SkASSERT(fMCStack.count() == 0 || fMCRec->fSaveCount <= fSaveCount);
|
| }
|
|
|
| SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) {
|
|
|