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