Close pending save() calls in QT debugger to avoid saveLayer() corruption.
http://codereview.appspot.com/6856076/
git-svn-id: http://skia.googlecode.com/svn/trunk@6565 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/debugger/SkDebugCanvas.cpp b/debugger/SkDebugCanvas.cpp
index 0c1c26b..af86a1e 100644
--- a/debugger/SkDebugCanvas.cpp
+++ b/debugger/SkDebugCanvas.cpp
@@ -20,7 +20,8 @@
}
SkDebugCanvas::SkDebugCanvas(int width, int height)
- : INHERITED(make_noconfig_bm(width, height)) {
+ : INHERITED(make_noconfig_bm(width, height))
+ , fOutstandingSaveCount(0) {
// TODO(chudy): Free up memory from all draw commands in destructor.
fWidth = width;
fHeight = height;
@@ -96,6 +97,9 @@
if (fIndex < index) {
i = fIndex + 1;
} else {
+ for (int j = 0; j < fOutstandingSaveCount; j++) {
+ canvas->restore();
+ }
i = 0;
canvas->clear(0);
canvas->resetMatrix();
@@ -103,6 +107,7 @@
SkIntToScalar(fHeight));
canvas->clipRect(rect, SkRegion::kReplace_Op );
applyUserTransform(canvas);
+ fOutstandingSaveCount = 0;
}
for (; i <= index; i++) {
@@ -122,6 +127,7 @@
if (commandVector[i]->isVisible()) {
commandVector[i]->execute(canvas);
+ commandVector[i]->trackSaveState(&fOutstandingSaveCount);
}
}
fMatrix = canvas->getTotalMatrix();
diff --git a/debugger/SkDebugCanvas.h b/debugger/SkDebugCanvas.h
index 1eeada2..2512702 100644
--- a/debugger/SkDebugCanvas.h
+++ b/debugger/SkDebugCanvas.h
@@ -209,6 +209,14 @@
SkIRect fClip;
/**
+ Number of unmatched save() calls at any point during a draw.
+ If there are any saveLayer() calls outstanding, we need to resolve
+ all of them, which in practice means resolving all save() calls,
+ to avoid corruption of our canvas.
+ */
+ int fOutstandingSaveCount;
+
+ /**
Adds the command to the classes vector of commands.
@param command The draw command for execution
*/
diff --git a/debugger/SkDrawCommand.cpp b/debugger/SkDrawCommand.cpp
index 5973ca8..322be7b 100644
--- a/debugger/SkDrawCommand.cpp
+++ b/debugger/SkDrawCommand.cpp
@@ -436,6 +436,10 @@
canvas->restore();
}
+void Restore::trackSaveState(int* state) {
+ (*state)--;
+}
+
Rotate::Rotate(SkScalar degrees) {
this->fDegrees = degrees;
this->fDrawType = ROTATE;
@@ -457,6 +461,10 @@
canvas->save(this->fFlags);
}
+void Save::trackSaveState(int* state) {
+ (*state)++;
+}
+
SaveLayer::SaveLayer(const SkRect* bounds, const SkPaint* paint,
SkCanvas::SaveFlags flags) {
this->fBounds = bounds;
@@ -473,6 +481,10 @@
canvas->saveLayer(this->fBounds, this->fPaint, this->fFlags);
}
+void SaveLayer::trackSaveState(int* state) {
+ (*state)++;
+}
+
Scale::Scale(SkScalar sx, SkScalar sy) {
this->fSx = sx;
this->fSy = sy;
diff --git a/debugger/SkDrawCommand.h b/debugger/SkDrawCommand.h
index cfb03e5..c6811f6 100644
--- a/debugger/SkDrawCommand.h
+++ b/debugger/SkDrawCommand.h
@@ -35,6 +35,9 @@
SkTDArray<SkString*>* Info() {return &fInfo; };
virtual void execute(SkCanvas* canvas)=0;
+ /** Does nothing by default, but used by save() and restore()-type
+ subclassse to track unresolved save() calls. */
+ virtual void trackSaveState(int* state) { };
DrawType getType() { return fDrawType; };
virtual const SkBitmap* getBitmap() const { return NULL; }
@@ -53,6 +56,7 @@
public:
Restore();
virtual void execute(SkCanvas* canvas) SK_OVERRIDE;
+ virtual void trackSaveState(int* state) SK_OVERRIDE;
};
class Clear : public SkDrawCommand {
@@ -314,6 +318,7 @@
public:
Save(SkCanvas::SaveFlags flags);
virtual void execute(SkCanvas* canvas) SK_OVERRIDE;
+ virtual void trackSaveState(int* state) SK_OVERRIDE;
private:
SkCanvas::SaveFlags fFlags;
};
@@ -323,6 +328,7 @@
SaveLayer(const SkRect* bounds, const SkPaint* paint,
SkCanvas::SaveFlags flags);
virtual void execute(SkCanvas* canvas) SK_OVERRIDE;
+ virtual void trackSaveState(int* state) SK_OVERRIDE;
private:
const SkRect* fBounds;
const SkPaint* fPaint;