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
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);
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);
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));
}
* 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) {
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) {
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;
/**
*/
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;
};