aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/utils/SkDeferredCanvas.h8
-rw-r--r--src/utils/SkDeferredCanvas.cpp13
-rw-r--r--tests/DeferredCanvasTest.cpp53
3 files changed, 73 insertions, 1 deletions
diff --git a/include/utils/SkDeferredCanvas.h b/include/utils/SkDeferredCanvas.h
index 907cb91575..5f781f8859 100644
--- a/include/utils/SkDeferredCanvas.h
+++ b/include/utils/SkDeferredCanvas.h
@@ -89,6 +89,11 @@ public:
bool isFreshFrame() const;
/**
+ * Returns canvas's size.
+ */
+ SkISize getCanvasSize() const;
+
+ /**
* Returns true if the canvas has recorded draw commands that have
* not yet been played back.
*/
@@ -250,6 +255,9 @@ private:
size_t fBitmapSizeThreshold;
bool fDeferredDrawing;
+ mutable SkISize fCachedCanvasSize;
+ mutable bool fCachedCanvasSizeDirty;
+
friend class SkDeferredCanvasTester; // for unit testing
typedef SkCanvas INHERITED;
};
diff --git a/src/utils/SkDeferredCanvas.cpp b/src/utils/SkDeferredCanvas.cpp
index b46e92a4a0..cce5dde538 100644
--- a/src/utils/SkDeferredCanvas.cpp
+++ b/src/utils/SkDeferredCanvas.cpp
@@ -526,6 +526,8 @@ SkDeferredCanvas::SkDeferredCanvas(SkDeferredDevice* device) : SkCanvas (device)
void SkDeferredCanvas::init() {
fBitmapSizeThreshold = kDeferredCanvasBitmapSizeThreshold;
fDeferredDrawing = true; // On by default
+ fCachedCanvasSize.setEmpty();
+ fCachedCanvasSizeDirty = true;
}
void SkDeferredCanvas::setMaxRecordingStorage(size_t maxStorage) {
@@ -589,6 +591,14 @@ bool SkDeferredCanvas::isFreshFrame() const {
return this->getDeferredDevice()->isFreshFrame();
}
+SkISize SkDeferredCanvas::getCanvasSize() const {
+ if (fCachedCanvasSizeDirty) {
+ fCachedCanvasSize = this->getBaseLayerSize();
+ fCachedCanvasSizeDirty = false;
+ }
+ return fCachedCanvasSize;
+}
+
bool SkDeferredCanvas::hasPendingCommands() const {
return this->getDeferredDevice()->hasPendingCommands();
}
@@ -609,6 +619,7 @@ SkSurface* SkDeferredCanvas::setSurface(SkSurface* surface) {
// all pending commands, which can help to seamlessly recover from
// a lost accelerated graphics context.
deferredDevice->setSurface(surface);
+ fCachedCanvasSizeDirty = true;
return surface;
}
@@ -632,7 +643,7 @@ SkImage* SkDeferredCanvas::newImageSnapshot() {
bool SkDeferredCanvas::isFullFrame(const SkRect* rect,
const SkPaint* paint) const {
SkCanvas* canvas = this->drawingCanvas();
- SkISize canvasSize = this->getDeviceSize();
+ SkISize canvasSize = this->getCanvasSize();
if (rect) {
if (!canvas->getTotalMatrix().rectStaysRect()) {
return false; // conservative
diff --git a/tests/DeferredCanvasTest.cpp b/tests/DeferredCanvasTest.cpp
index 61af550e20..89454256aa 100644
--- a/tests/DeferredCanvasTest.cpp
+++ b/tests/DeferredCanvasTest.cpp
@@ -839,6 +839,58 @@ static void TestDeferredCanvasCreateCompatibleDevice(skiatest::Reporter* reporte
REPORTER_ASSERT(reporter, notificationCounter.fStorageAllocatedChangedCount == 1);
}
+static void TestDeferredCanvasGetCanvasSize(skiatest::Reporter* reporter) {
+ SkRect rect;
+ rect.setXYWH(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(gWidth), SkIntToScalar(gHeight));
+ SkRect clip;
+ clip.setXYWH(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(1), SkIntToScalar(1));
+
+ SkPaint paint;
+ SkISize size = SkISize::Make(gWidth, gHeight);
+
+ SkAutoTUnref<SkSurface> surface(createSurface(0xFFFFFFFF));
+ SkAutoTUnref<SkDeferredCanvas> canvas(SkDeferredCanvas::Create(surface.get()));
+
+ for (int i = 0; i < 2; ++i) {
+ if (i == 1) {
+ SkSurface* newSurface = SkSurface::NewRasterPMColor(4, 4);
+ canvas->setSurface(newSurface);
+ size = SkISize::Make(4, 4);
+ }
+
+ // verify that canvas size is correctly initialized or set
+ REPORTER_ASSERT(reporter, size == canvas->getCanvasSize());
+
+ // Verify that clear, clip and draw the canvas will not change its size
+ canvas->clear(0x00000000);
+ canvas->clipRect(clip, SkRegion::kIntersect_Op, false);
+ canvas->drawRect(rect, paint);
+ REPORTER_ASSERT(reporter, size == canvas->getCanvasSize());
+
+ // Verify that flush the canvas will not change its size
+ canvas->flush();
+ REPORTER_ASSERT(reporter, size == canvas->getCanvasSize());
+
+ // Verify that clear canvas with saved state will not change its size
+ canvas->save();
+ canvas->clear(0xFFFFFFFF);
+ REPORTER_ASSERT(reporter, size == canvas->getCanvasSize());
+
+ // Verify that restore canvas state will not change its size
+ canvas->restore();
+ REPORTER_ASSERT(reporter, size == canvas->getCanvasSize());
+
+ // Verify that clear within a layer will not change canvas size
+ canvas->saveLayer(&clip, &paint);
+ canvas->clear(0x00000000);
+ REPORTER_ASSERT(reporter, size == canvas->getCanvasSize());
+
+ // Verify that restore from a layer will not change canvas size
+ canvas->restore();
+ REPORTER_ASSERT(reporter, size == canvas->getCanvasSize());
+ }
+}
+
DEF_TEST(DeferredCanvas_CPU, reporter) {
TestDeferredCanvasFlush(reporter);
TestDeferredCanvasSilentFlush(reporter);
@@ -850,6 +902,7 @@ DEF_TEST(DeferredCanvas_CPU, reporter) {
TestDeferredCanvasBitmapSizeThreshold(reporter);
TestDeferredCanvasCreateCompatibleDevice(reporter);
TestDeferredCanvasWritePixelsToSurface(reporter);
+ TestDeferredCanvasGetCanvasSize(reporter);
TestDeferredCanvasSurface(reporter, NULL);
TestDeferredCanvasSetSurface(reporter, NULL);
}