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
This commit is contained in:
reed@google.com 2012-07-30 21:03:46 +00:00
parent 97efada074
commit 9ea5a3bc73
6 changed files with 64 additions and 35 deletions

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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));
}

View File

@ -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) {}
SkSurface_Base::SkSurface_Base(int width, int height) : INHERITED(width, height) {
fCachedCanvas = NULL;
}
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*);
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) {

View File

@ -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;
};