Bug 635035, part 3: Add gfxASurface::MovePixels() interface and generic impl. sr=roc
authorChris Jones <jones.chris.g@gmail.com>
Wed, 09 Mar 2011 11:27:37 -0600
changeset 63368 173971a4af7efeaeead7a8b38a1c3abb9e879eee
parent 63367 5a3f1c4e63c198dfe1fef41ebb5bfb503ef4f66c
child 63369 d4a93181df15b4a678c0eeb6999e3f71c8fa5af7
push idunknown
push userunknown
push dateunknown
reviewersroc
bugs635035
milestone2.0b13pre
Bug 635035, part 3: Add gfxASurface::MovePixels() interface and generic impl. sr=roc
gfx/thebes/gfxASurface.cpp
gfx/thebes/gfxASurface.h
--- a/gfx/thebes/gfxASurface.cpp
+++ b/gfx/thebes/gfxASurface.cpp
@@ -35,18 +35,20 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIMemoryReporter.h"
 #include "nsMemory.h"
 
 #include "gfxASurface.h"
+#include "gfxContext.h"
+#include "gfxImageSurface.h"
 
-#include "gfxImageSurface.h"
+#include "nsRect.h"
 
 #include "cairo.h"
 
 #ifdef CAIRO_HAS_WIN32_SURFACE
 #include "gfxWindowsSurface.h"
 #endif
 #ifdef CAIRO_HAS_D2D_SURFACE
 #include "gfxD2DSurface.h"
@@ -469,16 +471,34 @@ gfxASurface::BytePerPixelFromFormat(gfxI
         case ImageFormatA8:
             return 1;
         default:
             NS_WARNING("Unknown byte per pixel value for Image format");
     }
     return 0;
 }
 
+void
+gfxASurface::MovePixels(const nsIntRect& aSourceRect,
+                        const nsIntPoint& aDestTopLeft)
+{
+    gfxIntSize size = GetSize();
+    nsIntRect dest(aDestTopLeft, aSourceRect.Size());
+    // Assume that our cairo backend already knows how to properly
+    // self-copy.  gfxASurface subtypes whose backend can't self-copy
+    // need their own implementations, or their backends need to be
+    // fixed.
+    nsRefPtr<gfxContext> ctx = new gfxContext(this);
+    ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
+    nsIntPoint srcOrigin = dest.TopLeft() - aSourceRect.TopLeft();
+    ctx->SetSource(this, gfxPoint(srcOrigin.x, srcOrigin.y));
+    ctx->Rectangle(gfxRect(dest.x, dest.y, dest.width, dest.height));
+    ctx->Fill();
+}
+
 /** Memory reporting **/
 
 static const char *sSurfaceNamesForSurfaceType[] = {
     "gfx/surface/image",
     "gfx/surface/pdf",
     "gfx/surface/ps",
     "gfx/surface/xlib",
     "gfx/surface/xcb",
--- a/gfx/thebes/gfxASurface.h
+++ b/gfx/thebes/gfxASurface.h
@@ -43,16 +43,18 @@
 #include "nsAutoPtr.h"
 
 typedef struct _cairo_surface cairo_surface_t;
 typedef struct _cairo_user_data_key cairo_user_data_key_t;
 
 typedef void (*thebes_destroy_func_t) (void *data);
 
 class gfxImageSurface;
+struct nsIntPoint;
+struct nsIntRect;
 
 /**
  * A surface is something you can draw on. Instantiate a subclass of this
  * abstract class, and use gfxContext to draw on this surface.
  */
 class THEBES_API gfxASurface {
 public:
     nsrefcnt AddRef(void);
@@ -216,16 +218,29 @@ public:
             return *mOpaqueRect;
         static const gfxRect empty(0, 0, 0, 0);
         return empty;
     }
 
     virtual PRBool SupportsSelfCopy() { return PR_TRUE; }
 
     /**
+     * Move the pixels in |aSourceRect| to |aDestTopLeft|.  Like with
+     * memmove(), |aSourceRect| and the rectangle defined by
+     * |aDestTopLeft| are allowed to overlap, and the effect is
+     * equivalent to copying |aSourceRect| to a scratch surface and
+     * then back to |aDestTopLeft|.
+     *
+     * |aSourceRect| and the destination rectangle defined by
+     * |aDestTopLeft| are clipped to this surface's bounds.
+     */
+    virtual void MovePixels(const nsIntRect& aSourceRect,
+                            const nsIntPoint& aDestTopLeft);
+
+    /**
      * Mark the surface as being allowed/not allowed to be used as a source.
      */
     void SetAllowUseAsSource(PRBool aAllow) { mAllowUseAsSource = aAllow; }
     PRBool GetAllowUseAsSource() { return mAllowUseAsSource; }
 
 protected:
     gfxASurface() : mSurface(nsnull), mFloatingRefs(0), mBytesRecorded(0),
                     mSurfaceValid(PR_FALSE), mAllowUseAsSource(PR_TRUE)