Override 32BPP format in SkCanvas::readPixels

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



git-svn-id: http://skia.googlecode.com/svn/trunk@2600 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index 00fdfbe..f7f918e 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -106,36 +106,75 @@
     ///////////////////////////////////////////////////////////////////////////
 
     /**
+     * This enum can be used with readPixels to perform a readback into an 8888
+     * format other than Skia's native format (SkPMColor). There are three byte
+     * orders supported: native, BGRA, and RGBA. Each has a premultiplied and
+     * unpremultiplied variant. Unlike the other 8888 configs, the native 8888
+     * config is defined by shift values rather than byte order. The conversion
+     * from the native config to a byte order must consider endianness.
+     */
+    enum Config8888 {
+        /**
+         * Skia's native order specified by:
+         *      SK_A32_SHIFT, SK_R32_SHIFT, SK_G32_SHIFT, and SK_B32_SHIFT
+         *
+         * kNative_Premul_Config8888 is equivalent to SkPMColor
+         * kNative_Unpremul_Config8888 has the same component order as SkPMColor
+         * but is not premultiplied.
+         */
+        kNative_Premul_Config8888,
+        kNative_Unpremul_Config8888,
+        /**
+         * low byte to high byte: B, G, R, A.
+         */
+        kBGRA_Premul_Config8888,
+        kBGRA_Unpremul_Config8888,
+        /**
+         * low byte to high byte: R, G, B, A.
+         */
+        kRGBA_Premul_Config8888,
+        kRGBA_Unpremul_Config8888,
+    };
+
+    /**
      *  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.
+     *  The canvas' pixels are converted to the bitmap's config. The only
+     *  supported config is kARGB_8888_Config, though this is likely to be
+     *  relaxed in  the future. The meaning of config kARGB_8888_Config is
+     *  modified by the enum param config8888. The default value interprets
+     *  kARGB_8888_Config as SkPMColor
      *
      *  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
-     *  }
+     *  Other failure conditions:
+     *    * If the canvas is backed by a non-raster device (e.g. PDF) then
+     *       readPixels will fail.
+     *    * If bitmap is texture-backed then readPixels will fail. (This may be
+     *       relaxed in the future.)
+     *
+     *  Example that reads the entire canvas into a bitmap using the native
+     *  SkPMColor:
+     *    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);
+    bool readPixels(SkBitmap* bitmap,
+                    int x, int y,
+                    Config8888 config8888 = kNative_Premul_Config8888);
 
     /**
      * DEPRECATED: This will be removed as soon as webkit is no longer relying
diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h
index 4dadfc4..488a004 100644
--- a/include/core/SkDevice.h
+++ b/include/core/SkDevice.h
@@ -107,26 +107,8 @@
     const SkBitmap& accessBitmap(bool changePixels);
 
     /**
-     *  Copy the pixels from the device into bitmap. Returns true on success.
-     *  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.
-     */
-    bool readPixels(SkBitmap* bitmap, int x, int y);
-
-    /**
+     *  DEPRECATED: This will be made protected once WebKit stops using it.
+     *              Instead use Canvas' writePixels method.
      *  Similar to draw sprite, this method will copy the pixels in bitmap onto
      *  the device, with the top/left corner specified by (x, y). The pixel
      *  values in the device are completely replaced: there is no blending.
@@ -254,6 +236,37 @@
     virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
                             const SkPaint&);
 
+    /**
+     *  On success (returns true), copy the device pixels into the bitmap.
+     *  On failure, the bitmap parameter is left unchanged and false is
+     *  returned.
+     *
+     *  The device's pixels are converted to the bitmap's config. The only
+     *  supported config is kARGB_8888_Config, though this is likely to be
+     *  relaxed in  the future. The meaning of config kARGB_8888_Config is
+     *  modified by the enum param config8888. The default value interprets
+     *  kARGB_8888_Config as SkPMColor
+     *
+     *  If the bitmap has pixels already allocated, the device 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 actual pixels written is the intersection of the device's 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.
+     *
+     *  Other failure conditions:
+     *    * If the device is not a raster device (e.g. PDF) then readPixels will
+     *      fail.
+     *    * If bitmap is texture-backed then readPixels will fail. (This may be
+     *      relaxed in the future.)
+     */
+    bool readPixels(SkBitmap* bitmap,
+                    int x, int y,
+                    SkCanvas::Config8888 config8888);
+
     ///////////////////////////////////////////////////////////////////////////
 
     /** Update as needed the pixel value in the bitmap, so that the caller can access
@@ -276,8 +289,9 @@
      *  3. The rectangle (x, y, x + bitmap->width(), y + bitmap->height()) is
      *     contained in the device bounds.
      */
-    virtual bool onReadPixels(const SkBitmap& bitmap, int x, int y);
-
+    virtual bool onReadPixels(const SkBitmap& bitmap,
+                              int x, int y,
+                              SkCanvas::Config8888 config8888);
 
     /** Called when this device is installed into a Canvas. Balanaced by a call
         to unlockPixels() when the device is removed from a Canvas.
@@ -285,6 +299,10 @@
     virtual void lockPixels();
     virtual void unlockPixels();
 
+    // This is equal kBGRA_Premul_Config8888 or kRGBA_Premul_Config8888 if 
+    // either is identical to kNative_Premul_Config8888. Otherwise, -1.
+    static const SkCanvas::Config8888 kPMColorAlias;
+
 private:
     friend class SkCanvas;
     friend struct DeviceCM; //for setMatrixClip
diff --git a/include/device/xps/SkXPSDevice.h b/include/device/xps/SkXPSDevice.h
index bac7f38..2ba20f0 100644
--- a/include/device/xps/SkXPSDevice.h
+++ b/include/device/xps/SkXPSDevice.h
@@ -143,7 +143,8 @@
 
     virtual bool onReadPixels(const SkBitmap& bitmap,
                               int x,
-                              int y) SK_OVERRIDE {
+                              int y,
+                              SkCanvas::Config8888) SK_OVERRIDE {
         return false;
     }
 
diff --git a/include/gpu/SkGpuDevice.h b/include/gpu/SkGpuDevice.h
index d394d12..631cc06 100644
--- a/include/gpu/SkGpuDevice.h
+++ b/include/gpu/SkGpuDevice.h
@@ -142,7 +142,8 @@
     
     // overrides from SkDevice
     virtual bool onReadPixels(const SkBitmap& bitmap,
-                              int x, int y) SK_OVERRIDE;
+                              int x, int y,
+                              SkCanvas::Config8888 config8888) SK_OVERRIDE;
 
 
 private:
diff --git a/include/pdf/SkPDFDevice.h b/include/pdf/SkPDFDevice.h
index 1e4db86..b74e98f 100644
--- a/include/pdf/SkPDFDevice.h
+++ b/include/pdf/SkPDFDevice.h
@@ -159,7 +159,8 @@
     
 protected:
     virtual bool onReadPixels(const SkBitmap& bitmap,
-                              int x, int y) SK_OVERRIDE {
+                              int x, int y,
+                              SkCanvas::Config8888) SK_OVERRIDE {
         return false;
     }