aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-07-30 21:03:46 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-07-30 21:03:46 +0000
commit9ea5a3bc7361cb88d37280b5922fba9430fed328 (patch)
treea16d1193b8b30ad47cfd578207335b5837765060
parent97efada074e4806479f1350ab1508939c2fdcb53 (diff)
change SkSurface::newCanvas() to getCanvas(), and redefine its life-cycle to be
a single canvas for the lifetime of the surface. Get a playback copy from the src picture, so we can continue to record into the original picture. git-svn-id: http://skia.googlecode.com/svn/trunk@4842 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--include/core/SkSurface.h11
-rw-r--r--src/image/SkImagePriv.cpp2
-rw-r--r--src/image/SkImagePriv.h7
-rw-r--r--src/image/SkImage_Picture.cpp14
-rw-r--r--src/image/SkSurface.cpp33
-rw-r--r--src/image/SkSurface_Base.h32
6 files changed, 64 insertions, 35 deletions
diff --git a/include/core/SkSurface.h b/include/core/SkSurface.h
index b399a2fe92..69889e5adc 100644
--- a/include/core/SkSurface.h
+++ b/include/core/SkSurface.h
@@ -71,13 +71,12 @@ public:
void notifyContentChanged();
/**
- * Return a canvas that will draw into this surface.
- *
- * LIFECYCLE QUESTIONS
- * 1. Is this owned by the surface or the caller?
- * 2. Can the caller get a 2nd canvas, or reset the state of the first?
+ * Return a canvas that will draw into this surface. This will always
+ * return the same canvas for a given surface, and is manged/owned by the
+ * surface. It should not be used when its parent surface has gone out of
+ * scope.
*/
- SkCanvas* newCanvas();
+ SkCanvas* getCanvas();
/**
* Return a new surface that is "compatible" with this one, in that it will
diff --git a/src/image/SkImagePriv.cpp b/src/image/SkImagePriv.cpp
index a826e80f9a..67d31b746a 100644
--- a/src/image/SkImagePriv.cpp
+++ b/src/image/SkImagePriv.cpp
@@ -133,8 +133,10 @@ void SkImagePrivDrawPicture(SkCanvas* canvas, SkPicture* picture,
x + SkIntToScalar(picture->width()),
y + SkIntToScalar(picture->height()));
canvas->saveLayer(&bounds, paint);
+ canvas->translate(x, y);
} else if (x || y) {
canvas->save();
+ canvas->translate(x, y);
}
canvas->drawPicture(*picture);
diff --git a/src/image/SkImagePriv.h b/src/image/SkImagePriv.h
index f69eaac4d4..c0aff983a2 100644
--- a/src/image/SkImagePriv.h
+++ b/src/image/SkImagePriv.h
@@ -30,7 +30,12 @@ extern SkImage* SkNewImageFromBitmap(const SkBitmap&);
extern void SkImagePrivDrawPicture(SkCanvas*, SkPicture*,
SkScalar x, SkScalar y, const SkPaint*);
-extern SkImage* SkNewImageFromPicture(SkPicture*);
+
+/**
+ * Return an SkImage whose contents are those of the specified picture. Note:
+ * The picture itself is unmodified, and may continue to be used for recording
+ */
+extern SkImage* SkNewImageFromPicture(const SkPicture*);
static inline size_t SkImageMinRowBytes(const SkImage::Info& info) {
size_t rb = info.fWidth * SkImageBytesPerPixel(info.fColorType);
diff --git a/src/image/SkImage_Picture.cpp b/src/image/SkImage_Picture.cpp
index c93c06fab5..959e47bd06 100644
--- a/src/image/SkImage_Picture.cpp
+++ b/src/image/SkImage_Picture.cpp
@@ -39,7 +39,17 @@ void SkImage_Picture::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
SkImagePrivDrawPicture(canvas, fPicture, x, y, paint);
}
-SkImage* SkNewImageFromPicture(SkPicture* pict) {
- return SkNEW_ARGS(SkImage_Picture, (pict));
+SkImage* SkNewImageFromPicture(const SkPicture* srcPicture) {
+ /**
+ * We want to snapshot the playback status of the picture, w/o affecting
+ * its ability to continue recording (if needed).
+ *
+ * Optimally this will shared as much data/buffers as it can with
+ * srcPicture, and srcPicture will perform a copy-on-write as needed if it
+ * needs to mutate them later on.
+ */
+ SkAutoTUnref<SkPicture> playback(SkNEW_ARGS(SkPicture, (*srcPicture)));
+
+ return SkNEW_ARGS(SkImage_Picture, (playback));
}
diff --git a/src/image/SkSurface.cpp b/src/image/SkSurface.cpp
index f442c4d219..e7695c9df8 100644
--- a/src/image/SkSurface.cpp
+++ b/src/image/SkSurface.cpp
@@ -5,34 +5,19 @@
* found in the LICENSE file.
*/
-#include "SkSurface.h"
+#include "SkSurface_Base.h"
#include "SkImagePriv.h"
#include "SkCanvas.h"
///////////////////////////////////////////////////////////////////////////////
-class SkSurface_Base : public SkSurface {
-public:
- SkSurface_Base(int width, int height) : INHERITED(width, height) {}
-
- virtual SkCanvas* onNewCanvas() = 0;
- virtual SkSurface* onNewSurface(const SkImage::Info&, SkColorSpace*) = 0;
- virtual SkImage* onNewImageShapshot() = 0;
-
- /**
- * Default implementation:
- *
- * image = this->newImageSnapshot();
- * if (image) {
- * image->draw(canvas, ...);
- * image->unref();
- * }
- */
- virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*);
+SkSurface_Base::SkSurface_Base(int width, int height) : INHERITED(width, height) {
+ fCachedCanvas = NULL;
+}
-private:
- typedef SkSurface INHERITED;
-};
+SkSurface_Base::~SkSurface_Base() {
+ SkSafeUnref(fCachedCanvas);
+}
void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
const SkPaint* paint) {
@@ -55,8 +40,8 @@ SkSurface::SkSurface(int width, int height) : fWidth(width), fHeight(height) {
fGenerationID = 0;
}
-SkCanvas* SkSurface::newCanvas() {
- return asSB(this)->onNewCanvas();
+SkCanvas* SkSurface::getCanvas() {
+ return asSB(this)->getCachedCanvas();
}
SkSurface* SkSurface::newSurface(const SkImage::Info& info, SkColorSpace* cs) {
diff --git a/src/image/SkSurface_Base.h b/src/image/SkSurface_Base.h
index bb6de961b0..5a803fa731 100644
--- a/src/image/SkSurface_Base.h
+++ b/src/image/SkSurface_Base.h
@@ -12,10 +12,25 @@
class SkSurface_Base : public SkSurface {
public:
- SkSurface_Base(int width, int height) : INHERITED(width, height) {}
-
+ SkSurface_Base(int width, int height);
+ virtual ~SkSurface_Base();
+
+ /**
+ * Allocate a canvas that will draw into this surface. We will cache this
+ * canvas, to return the same object to the caller multiple times. We
+ * take ownership, and will call unref() on the canvas when we go out of
+ * scope.
+ */
virtual SkCanvas* onNewCanvas() = 0;
+
virtual SkSurface* onNewSurface(const SkImage::Info&, SkColorSpace*) = 0;
+
+ /**
+ * Allocate an SkImage that represents the current contents of the surface.
+ * This needs to be able to outlive the surface itself (if need be), and
+ * must faithfully represent the current contents, even if the surface
+ * is chaged after this calle (e.g. it is drawn to via its canvas).
+ */
virtual SkImage* onNewImageShapshot() = 0;
/**
@@ -29,7 +44,20 @@ public:
*/
virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*);
+ /**
+ * Returns a the result of onNewCanvas(), but caches it so that only one
+ * canvas never ever be created.
+ */
+ SkCanvas* getCachedCanvas() {
+ if (NULL == fCachedCanvas) {
+ fCachedCanvas = this->onNewCanvas();
+ }
+ return fCachedCanvas;
+ }
+
private:
+ SkCanvas* fCachedCanvas;
+
typedef SkSurface INHERITED;
};