diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/SkBitmapDevice.cpp | 34 | ||||
-rw-r--r-- | src/core/SkCanvas.cpp | 97 | ||||
-rw-r--r-- | src/core/SkDevice.cpp | 21 |
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; } |