change SkSurface::newCanvas() to getCanvas(), and redefine its life-cycle to be
authorreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 30 Jul 2012 21:03:46 +0000 (21:03 +0000)
committerreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 30 Jul 2012 21:03:46 +0000 (21:03 +0000)
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
src/image/SkImagePriv.cpp
src/image/SkImagePriv.h
src/image/SkImage_Picture.cpp
src/image/SkSurface.cpp
src/image/SkSurface_Base.h

index b399a2f..69889e5 100644 (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
index a826e80..67d31b7 100644 (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);
index f69eaac..c0aff98 100644 (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);
index c93c06f..959e47b 100644 (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));
 }
 
index f442c4d..e7695c9 100644 (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) {}
-
-    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) {
index bb6de96..5a803fa 100644 (file)
 
 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;
 };