From 9ea5a3bc7361cb88d37280b5922fba9430fed328 Mon Sep 17 00:00:00 2001 From: "reed@google.com" Date: Mon, 30 Jul 2012 21:03:46 +0000 Subject: 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 --- include/core/SkSurface.h | 11 +++++------ src/image/SkImagePriv.cpp | 2 ++ src/image/SkImagePriv.h | 7 ++++++- src/image/SkImage_Picture.cpp | 14 ++++++++++++-- src/image/SkSurface.cpp | 33 +++++++++------------------------ src/image/SkSurface_Base.h | 32 ++++++++++++++++++++++++++++++-- 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 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; }; -- cgit v1.2.3