aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/SkBitmapDevice.cpp34
-rw-r--r--src/core/SkCanvas.cpp97
-rw-r--r--src/core/SkDevice.cpp21
3 files changed, 132 insertions, 20 deletions
diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp
index 476a124647..868306ca2e 100644
--- a/src/core/SkBitmapDevice.cpp
+++ b/src/core/SkBitmapDevice.cpp
@@ -173,6 +173,7 @@ bool SkBitmapDevice::allowImageFilter(const SkImageFilter*) {
return true;
}
+#ifdef SK_SUPPORT_LEGACY_READPIXELSCONFIG
bool SkBitmapDevice::onReadPixels(const SkBitmap& bitmap,
int x, int y,
SkCanvas::Config8888 config8888) {
@@ -198,6 +199,7 @@ bool SkBitmapDevice::onReadPixels(const SkBitmap& bitmap,
SkCopyBitmapToConfig8888(bmpPixels, bitmap.rowBytes(), config8888, subset);
return true;
}
+#endif
void* SkBitmapDevice::onAccessPixels(SkImageInfo* info, size_t* rowBytes) {
if (fBitmap.getPixels()) {
@@ -246,8 +248,8 @@ static bool info2config8888(const SkImageInfo& info, SkCanvas::Config8888* confi
// TODO: make this guy real, and not rely on legacy config8888 utility
#include "SkConfig8888.h"
-static bool write_pixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
- const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRowBytes) {
+static bool copy_pixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
+ const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRowBytes) {
if (srcInfo.dimensions() != dstInfo.dimensions()) {
return false;
}
@@ -295,13 +297,39 @@ bool SkBitmapDevice::onWritePixels(const SkImageInfo& srcInfo, const void* srcPi
void* dstPixels = fBitmap.getAddr(x, y);
size_t dstRowBytes = fBitmap.rowBytes();
- if (write_pixels(dstInfo, dstPixels, dstRowBytes, srcInfo, srcPixels, srcRowBytes)) {
+ if (copy_pixels(dstInfo, dstPixels, dstRowBytes, srcInfo, srcPixels, srcRowBytes)) {
fBitmap.notifyPixelsChanged();
return true;
}
return false;
}
+bool SkBitmapDevice::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
+ int x, int y) {
+ // since we don't stop creating un-pixeled devices yet, check for no pixels here
+ if (NULL == fBitmap.getPixels()) {
+ return false;
+ }
+
+ SkImageInfo srcInfo = fBitmap.info();
+
+ // perhaps can relax these in the future
+ if (4 != dstInfo.bytesPerPixel()) {
+ return false;
+ }
+ if (4 != srcInfo.bytesPerPixel()) {
+ return false;
+ }
+
+ srcInfo.fWidth = dstInfo.width();
+ srcInfo.fHeight = dstInfo.height();
+
+ const void* srcPixels = fBitmap.getAddr(x, y);
+ const size_t srcRowBytes = fBitmap.rowBytes();
+
+ return copy_pixels(dstInfo, dstPixels, dstRowBytes, srcInfo, srcPixels, srcRowBytes);
+}
+
///////////////////////////////////////////////////////////////////////////////
void SkBitmapDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 17e03c2373..ef6a82d9bf 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -667,6 +667,7 @@ SkBaseDevice* SkCanvas::setRootDevice(SkBaseDevice* device) {
return device;
}
+#ifdef SK_SUPPORT_LEGACY_READPIXELSCONFIG
bool SkCanvas::readPixels(SkBitmap* bitmap,
int x, int y,
Config8888 config8888) {
@@ -676,28 +677,95 @@ bool SkCanvas::readPixels(SkBitmap* bitmap,
}
return device->readPixels(bitmap, x, y, config8888);
}
+#endif
+
+bool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y) {
+ if (kUnknown_SkColorType == bitmap->colorType() || bitmap->getTexture()) {
+ return false;
+ }
+
+ bool weAllocated = false;
+ if (NULL == bitmap->pixelRef()) {
+ if (!bitmap->allocPixels()) {
+ return false;
+ }
+ weAllocated = true;
+ }
+
+ SkBitmap bm(*bitmap);
+ bm.lockPixels();
+ if (bm.getPixels() && this->readPixels(bm.info(), bm.getPixels(), bm.rowBytes(), x, y)) {
+ return true;
+ }
+
+ if (weAllocated) {
+ bitmap->setPixelRef(NULL);
+ }
+ return false;
+}
bool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
- SkBaseDevice* device = this->getDevice();
- if (!device) {
+ SkIRect r = srcRect;
+ const SkISize size = this->getBaseLayerSize();
+ if (!r.intersect(0, 0, size.width(), size.height())) {
+ bitmap->reset();
return false;
}
- SkIRect bounds;
- bounds.set(0, 0, device->width(), device->height());
- if (!bounds.intersect(srcRect)) {
+ if (!bitmap->allocN32Pixels(r.width(), r.height())) {
+ // bitmap will already be reset.
+ return false;
+ }
+ if (!this->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), r.x(), r.y())) {
+ bitmap->reset();
return false;
}
+ return true;
+}
- SkBitmap tmp;
- tmp.setConfig(SkBitmap::kARGB_8888_Config, bounds.width(),
- bounds.height());
- if (this->readPixels(&tmp, bounds.fLeft, bounds.fTop)) {
- bitmap->swap(tmp);
- return true;
- } else {
+bool SkCanvas::readPixels(const SkImageInfo& origInfo, void* dstP, size_t rowBytes, int x, int y) {
+ switch (origInfo.colorType()) {
+ case kUnknown_SkColorType:
+ case kIndex_8_SkColorType:
+ return false;
+ default:
+ break;
+ }
+ if (NULL == dstP || rowBytes < origInfo.minRowBytes()) {
+ return false;
+ }
+ if (0 == origInfo.width() || 0 == origInfo.height()) {
+ return false;
+ }
+
+ SkBaseDevice* device = this->getDevice();
+ if (!device) {
+ return false;
+ }
+
+ const SkISize size = this->getBaseLayerSize();
+ SkIRect srcR = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height());
+ if (!srcR.intersect(0, 0, size.width(), size.height())) {
return false;
}
+
+ SkImageInfo info = origInfo;
+ // the intersect may have shrunk info's logical size
+ info.fWidth = srcR.width();
+ info.fHeight = srcR.height();
+
+ // if x or y are negative, then we have to adjust pixels
+ if (x > 0) {
+ x = 0;
+ }
+ if (y > 0) {
+ y = 0;
+ }
+ // here x,y are either 0 or negative
+ dstP = ((char*)dstP - y * rowBytes - x * info.bytesPerPixel());
+
+ // The device can assert that the requested area is always contained in its bounds
+ return device->readPixels(info, dstP, rowBytes, srcR.x(), srcR.y());
}
bool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) {
@@ -1063,12 +1131,9 @@ SkAutoROCanvasPixels::SkAutoROCanvasPixels(SkCanvas* canvas) {
fAddr = canvas->peekPixels(&fInfo, &fRowBytes);
if (NULL == fAddr) {
fInfo = canvas->imageInfo();
- if (kUnknown_SkColorType == fInfo.colorType() ||
- !fBitmap.allocPixels(fInfo))
- {
+ if (kUnknown_SkColorType == fInfo.colorType() || !fBitmap.allocPixels(fInfo)) {
return; // failure, fAddr is NULL
}
- fBitmap.lockPixels();
if (!canvas->readPixels(&fBitmap, 0, 0)) {
return; // failure, fAddr is NULL
}
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 5b6ecc07f8..61a7ab61c7 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -112,6 +112,7 @@ const SkBitmap& SkBaseDevice::accessBitmap(bool changePixels) {
return bitmap;
}
+#ifdef SK_SUPPORT_LEGACY_READPIXELSCONFIG
bool SkBaseDevice::readPixels(SkBitmap* bitmap, int x, int y,
SkCanvas::Config8888 config8888) {
if (SkBitmap::kARGB_8888_Config != bitmap->config() ||
@@ -154,6 +155,10 @@ bool SkBaseDevice::readPixels(SkBitmap* bitmap, int x, int y,
}
return result;
}
+bool SkBaseDevice::onReadPixels(const SkBitmap&, int x, int y, SkCanvas::Config8888) {
+ return false;
+}
+#endif
SkSurface* SkBaseDevice::newSurface(const SkImageInfo&) { return NULL; }
@@ -171,6 +176,20 @@ void SkBaseDevice::drawDRRect(const SkDraw& draw, const SkRRect& outer,
this->drawPath(draw, path, paint, preMatrix, pathIsMutable);
}
+bool SkBaseDevice::readPixels(const SkImageInfo& info, void* dstP, size_t rowBytes, int x, int y) {
+#ifdef SK_DEBUG
+ SkASSERT(info.width() > 0 && info.height() > 0);
+ SkASSERT(dstP);
+ SkASSERT(rowBytes >= info.minRowBytes());
+ SkASSERT(x >= 0 && y >= 0);
+
+ const SkImageInfo& srcInfo = this->imageInfo();
+ SkASSERT(x + info.width() <= srcInfo.width());
+ SkASSERT(y + info.height() <= srcInfo.height());
+#endif
+ return this->onReadPixels(info, dstP, rowBytes, x, y);
+}
+
bool SkBaseDevice::writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes,
int x, int y) {
#ifdef SK_DEBUG
@@ -190,7 +209,7 @@ bool SkBaseDevice::onWritePixels(const SkImageInfo&, const void*, size_t, int, i
return false;
}
-bool SkBaseDevice::onReadPixels(const SkBitmap&, int x, int y, SkCanvas::Config8888) {
+bool SkBaseDevice::onReadPixels(const SkImageInfo&, void*, size_t, int x, int y) {
return false;
}