Changes the SkCanvas::readPixels API. Allows caller to read into prealloced bitmap pixels. Changes how clipping to device bounds is handled.

Review URL: http://codereview.appspot.com/5307077/



git-svn-id: http://skia.googlecode.com/svn/trunk@2584 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/core/SkBitmap.h b/include/core/SkBitmap.h
index e98a294..ae56739 100644
--- a/include/core/SkBitmap.h
+++ b/include/core/SkBitmap.h
@@ -225,12 +225,11 @@
     /** Copies the bitmap's pixels to the location pointed at by dst and returns
         true if possible, returns false otherwise.
 
-        In the event that the bitmap's stride is equal to dstRowBytes, and if
-        it is greater than strictly required by the bitmap's current config
-        (this may happen if the bitmap is an extracted subset of another), then
-        this function will copy bytes past the eand of each row, excluding the
-        last row. No copies are made outside of the declared size of dst,
-        however.
+        In the case when the dstRowBytes matches the bitmap's rowBytes, the copy
+        may be made faster by copying over the dst's per-row padding (for all
+        rows but the last). By setting preserveDstPad to true the caller can
+        disable this optimization and ensure that pixels in the padding are not
+        overwritten.
 
         Always returns false for RLE formats.
 
@@ -239,8 +238,10 @@
                         pixels using indicated stride.
         @param dstRowBytes  Width of each line in the buffer. If -1, uses
                             bitmap's internal stride.
+        @param preserveDstPad Must we preserve padding in the dst
     */
-    bool copyPixelsTo(void* const dst, size_t dstSize, int dstRowBytes = -1)
+    bool copyPixelsTo(void* const dst, size_t dstSize, int dstRowBytes = -1,
+                      bool preserveDstPad = false)
          const;
 
     /** Use the standard HeapAllocator to create the pixelref that manages the
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index b2bdafe..90bc1f4 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -105,14 +105,45 @@
 
     ///////////////////////////////////////////////////////////////////////////
 
+    /**

+     *  On success (returns true), copy the canvas pixels into the bitmap.

+     *  On failure, the bitmap parameter is left unchanged and false is

+     *  returned.

+     *

+     *  If the canvas is backed by a non-raster device (e.g. PDF) then

+     *  readPixels will fail.

+     *

+     *  If the bitmap has pixels already allocated, the canvas pixels will be

+     *  written there. If not, bitmap->allocPixels() will be called 

+     *  automatically. If the bitmap is backed by a texture readPixels will

+     *  fail.

+     *

+     *  The canvas' pixels are converted to the bitmap's config. The only

+     *  supported config is kARGB_8888_Config, though this may be relaxed in

+     *  future.

+     *

+     *  The actual pixels written is the intersection of the canvas' bounds, and

+     *  the rectangle formed by the bitmap's width,height and the specified x,y.

+     *  If bitmap pixels extend outside of that intersection, they will not be

+     *  modified.

+     *

+     *  Example that reads the entire canvas into a bitmap:

+     *  SkISize size = canvas->getDeviceSize();

+     *  bitmap->setConfig(SkBitmap::kARGB_8888_Config, size.fWidth,

+     *                                                 size.fHeight);

+     *  if (canvas->readPixels(bitmap, 0, 0)) {

+     *     // use the pixels

+     *  }

+     */
+    bool readPixels(SkBitmap* bitmap, int x, int y);
+
     /**
-     *  Copy the pixels from the device into bitmap. Returns true on success.
-     *  If false is returned, then the bitmap parameter is left unchanged.
-     *  The bitmap parameter is treated as output-only, and will be completely
-     *  overwritten (if the method returns true).
+     * DEPRECATED: This will be removed as soon as webkit is no longer relying
+     * on it. The bitmap is resized to the intersection of srcRect and the
+     * canvas bounds. New pixels are always allocated on success. Bitmap is
+     * unmodified on failure.
      */
     bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap);
-    bool readPixels(SkBitmap* bitmap);
 
     /**
      *  Similar to draw sprite, this method will copy the pixels in bitmap onto
diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h
index 95b6389..5d184e4 100644
--- a/include/core/SkDevice.h
+++ b/include/core/SkDevice.h
@@ -108,11 +108,23 @@
 
     /**
      *  Copy the pixels from the device into bitmap. Returns true on success.
-     *  If false is returned, then the bitmap parameter is left unchanged.
-     *  The bitmap parameter is treated as output-only, and will be completely
-     *  overwritten (if the method returns true).
+     *  If false is returned, then the bitmap parameter is left unchanged. The
+     *  rectangle read is defined by x, y and the bitmap's width and height.
+     *
+     *  If the bitmap has pixels allocated the canvas will write directly to
+     *  into that memory (if the call succeeds).
+     *
+     *  The read is clipped to the device bounds. If bitmap pixels were
+     *  preallocated then pixels outside the clip are left unmodified. If the
+     *  call allocates bitmap pixels then pixels outside the clip will be
+     *  uninitialized.
+     *
+     *  Currently bitmap must have kARGB_8888_Config or readPixels will fail.
+     *  This will likely be relaxed in the future.
+     *
+     *  The bitmap parameter is not modified if the call fails.
      */
-    virtual bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap);
+    bool readPixels(SkBitmap* bitmap, int x, int y);
 
     /**
      *  Similar to draw sprite, this method will copy the pixels in bitmap onto
@@ -256,6 +268,17 @@
         fBitmap.setPixelRef(pr, offset);
         return pr;
     }
+    
+    /**
+     * Implements readPixels API. The caller will ensure that:
+     *  1. bitmap has pixel config kARGB_8888_Config.
+     *  2. bitmap has pixels.
+     *  3. The rectangle (x, y, x + bitmap->width(), y + bitmap->height()) is
+     *     contained in the device bounds.
+     *  4. the bitmap struct is safe to partially overwrite in case of failure
+     */
+    virtual bool onReadPixels(const SkBitmap* bitmap, int x, int y);
+
 
     /** Called when this device is installed into a Canvas. Balanaced by a call
         to unlockPixels() when the device is removed from a Canvas.
diff --git a/include/device/xps/SkXPSDevice.h b/include/device/xps/SkXPSDevice.h
index 1fb9220..ed61ced 100644
--- a/include/device/xps/SkXPSDevice.h
+++ b/include/device/xps/SkXPSDevice.h
@@ -71,11 +71,6 @@
         return kVector_Capability;
     }
 
-    virtual bool readPixels(const SkIRect& srcRect,
-                            SkBitmap* bitmap) SK_OVERRIDE {
-        return false;
-    }
-
 protected:
     virtual void clear(SkColor color) SK_OVERRIDE;
 
@@ -146,6 +141,12 @@
         int x, int y,
         const SkPaint& paint) SK_OVERRIDE;
 
+    virtual bool onReadPixels(const SkBitmap* bitmap,
+                              int x,
+                              int y) SK_OVERRIDE {
+        return false;
+    }
+
 private:
     class TypefaceUse : ::SkNoncopyable {
     public:
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index f980702..d61b8bb 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -432,6 +432,8 @@
      * @param height        height of rectangle to read in pixels.
      * @param config        the pixel config of the destination buffer
      * @param buffer        memory to read the rectangle into.
+     * @param rowBytes      number of bytes bewtween consecueive rows. Zero
+     *                      means rows are tightly packed.
      *
      * @return true if the read succeeded, false if not. The read can fail
      *              because of a unsupported pixel config or because no render
@@ -439,7 +441,8 @@
      */
     bool readRenderTargetPixels(GrRenderTarget* target,
                                 int left, int top, int width, int height,
-                                GrPixelConfig config, void* buffer);
+                                GrPixelConfig config, void* buffer, 
+                                size_t rowBytes = 0);
 
     /**
      * Reads a rectangle of pixels from a texture.
diff --git a/include/gpu/GrGLDefines.h b/include/gpu/GrGLDefines.h
index 7a3d676..5d11b9f 100644
--- a/include/gpu/GrGLDefines.h
+++ b/include/gpu/GrGLDefines.h
@@ -348,7 +348,9 @@
 #define GR_GL_EXTENSIONS                     0x1F03
 
 /* Pixel Mode / Transfer */
-#define GR_GL_UNPACK_ROW_LENGTH            0x0CF2
+#define GR_GL_UNPACK_ROW_LENGTH              0x0CF2
+#define GR_GL_PACK_ROW_LENGTH                0x0D02
+
 
 /* TextureMagFilter */
 #define GR_GL_NEAREST                        0x2600
diff --git a/include/gpu/SkGpuDevice.h b/include/gpu/SkGpuDevice.h
index f5613a7..047fd07 100644
--- a/include/gpu/SkGpuDevice.h
+++ b/include/gpu/SkGpuDevice.h
@@ -68,7 +68,6 @@
     // overrides from SkDevice
 
     virtual void clear(SkColor color);
-    virtual bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap);
     virtual void writePixels(const SkBitmap& bitmap, int x, int y);
 
     virtual void setMatrixClip(const SkMatrix& matrix, const SkRegion& clip,
@@ -140,6 +139,11 @@
         TexCache        fTex;
     };
     friend class SkAutoTexCache;
+    
+    // overrides from SkDevice
+    virtual bool onReadPixels(const SkBitmap* bitmap,
+                              int x, int y) SK_OVERRIDE;
+
 
 private:
     GrContext*      fContext;
diff --git a/include/pdf/SkPDFDevice.h b/include/pdf/SkPDFDevice.h
index 9e985e7..b25e39a 100644
--- a/include/pdf/SkPDFDevice.h
+++ b/include/pdf/SkPDFDevice.h
@@ -66,10 +66,6 @@
 
     virtual void clear(SkColor color);
 
-    virtual bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
-        return false;
-    }
-
     /** These are called inside the per-device-layer loop for each draw call.
      When these are called, we have already applied any saveLayer operations,
      and are handling any looping from the paint, and any effects from the
@@ -160,6 +156,13 @@
     const SkPDFGlyphSetMap& getFontGlyphUsage() const {
         return *(fFontGlyphUsage.get());
     }
+    
+protected:
+    virtual bool onReadPixels(const SkBitmap* bitmap,
+                              int x, int y) SK_OVERRIDE {
+        return false;
+    }
+
 
 private:
     // TODO(vandebo): push most of SkPDFDevice's state into a core object in